Ember.js Route with searchquery causes: UnrecognizedURLError - ember.js

In my app I have a searchformula with dynamic input fields. The form leads then to the following URL:
/trefferliste/?modulId=1&modus=dokument&identnummer=XXX
my route definition:
this.resource('trefferliste', { 'path' : 'trefferliste/:query' });
until this point it works, but when i refresh the page it says: UnrecognizedURLError
in the trefferliste route I load the data with following statement:
return this.store.find('trefferliste', params.query);
I figured out, that the "?" causes the problem, but I need it for my store find query. So, can someone tell me how to define my route?
UPDATE: Here is a jsbin: http://emberjs.jsbin.com/nesehuxugi
Steps to reproduce the error:
Push the Button > then refresh the page and look into the console!
some additional informations:
DEBUG: Ember : 1.12.1
ember-template-compiler.js:163 DEBUG: Ember Data : 1.0.0-beta.17
ember-template-compiler.js:163 DEBUG: jQuery : 1.11.2

Use query params instead of dynamic segments, so characters with special meaning to URL schema will be escaped and your application routing will work even on refresh.
URL becomes: http://app.com#/trefferliste?query=%3FmodulId%3D1%26modus%3Ddokument%26identnummer%3DXXX, but you have to respect Ember.js and global URL conventions.
Working demo.
Code:
App = Ember.Application.create();
App.Router.map(function() {
this.resource('trefferliste');
});
App.IndexRoute = Ember.Route.extend({
model: function() {
return ['red', 'yellow', 'blue'];
}
});
App.TrefferlisteController = Ember.Controller.extend({
queryParams: ['query'],
query: null
});
App.IndexController = Ember.ObjectController.extend({
actions: {
suche: function() {
var query = "?modulId=1&modus=dokument&identnummer=XXX";
this.transitionTo('trefferliste', { queryParams: { query: query } });
}
}
});

Related

Ember data single data extract through browser URL

Getting all articles is ok, but when try to retrieve just one article through route url directly, system error - undefined
var articles = Ember.$.getJSON('http://localhost/emberdata/api/articles');
will return:
[{"articles":
[
{
"id":1,
"title":"Ember is the best",
"author":"brk","excerpt":"Programming is awesome"
},
{
"id":2,
"title":"Backbone not a framework",
"author":"krb",
"excerpt":"Server-side controller sucks"
},
{
"id":3,
"title":"Javascript pwned",
"author":"rbk",
"excerpt":"I know right"
}
]
}]
API is created using PHP Slim Rest API
this Route working find, showing all the data in the handlebar template
App.ArticlesRoute = Ember.Route.extend({
model: function() {
return articles;
}
});
However for child view routing, undefined is returned
App.ArticleRoute = Ember.Route.extend({
model: function(params) {
var article = articles.findBy('id', params.article_id);
console.log(article);
return article;
}
});
Directly invoking the child view URL is not working:
http://localhost/emberdata/#/articles/1
However clicking the link of articles, those child view route works:
this.resource('article', { path: ':article_id' });
This is the error:
Ember.$.getJSON() will return a promise (see: http://emberjs.com/api/classes/Ember.PromiseProxyMixin.html). You can't call the findBy() method on a promise.
That being said, you're making it yourself very difficult. I recommend to start using the DS.RESTAdapter. In your case it would be something like this:
App.ApplicationAdapter = DS.RESTAdapter.extend({
namespace: 'emberdata/api'
});
then clear (or remove) ArticlesRoute because you will use convention (instead of configuration):
App.ArticlesRoute = Ember.Route.extend({
});
idem for ArticleRoute. Except, if your backend doesn't support calls like /emberdata/api/article/1 use the following code:
App.ArticleRoute = Ember.Route.extend({
model: function(params) {
var article = this.store.find('article').findBy('id', params.article_id);
console.log(article);
return article;
}
});

how to receive variables sent by transitionToRoute

I read at
http://emberjs.com/guides/controllers/
the following code:
I have a search box and want to send the value of the search box to the SearchController.
App.ApplicationController = Ember.Controller.extend({ // the initial
value of the `search` property search: '',
actions: {
query: function() {
// the current value of the text field
var query = this.get('search');
this.transitionToRoute('search', { query: query });
} } });
How can i get the query parameter in the SearchController and then show it in search.hbs?
I am working with ember- cli.
The router is
import Ember from 'ember';
var Router = Ember.Router.extend({
location: NENV.locationType
});
Router.map(function() {
this.route('search');
});
export default Router;
I set up a route under routes/search.js
export default Ember.Route.extend({
model : function (params) {
console.debug("hi");
return params;
},
setupController: function(controller,model) {
var query = model.query;
console.debug("query is");
console.debug(query);
}
});
When debugging i get an error:
ember More context objects were passed than there are dynamic segments
Thanks,
David
You need to define your search route to be dynamic, so if you change your route definition to something like this
Router.map(function() {
this.resource('search', {path: '/search/:query});
})
This should work as you are expecting. Let me know if anything.
Cheers!

Ember.js setting application property on load

I'm trying to fetch the current logged in user via my REST API and then set it as a property of the ApplicationController. This is how I'm trying to do it:
App.ApplicationController = Ember.Controller.extend({
init: function() {
this._super();
var self = this;
App.User.findCurrent().then(function(user) {
self.set('currentUser', user);
});
}
});
App.User = Ember.Object.extend({});
App.User.reopenClass({
findCurrent: function() {
return $.getJSON('/api/v1/users/current').then(
function(response) {
return response.user;
}
);
}
});
When I check the Chrome network tab, I see there's a call to the API and the JSON is returned, but when I try to access e.g. {{currentUser.name}} in my application template (or a partial of it), it doesn't return the name. No errors are given as well.
But in the application template it doesn't return it.
What am I missing?
Thanks!
Edit
When I create another controller, e.g. HelpController and visit /help, then {{currentUser.name}} does return the username:
App.HelpController = Ember.Controller.extend({
needs: ['application'],
currentUser: Ember.computed.alias('controllers.application.currentUser')
});
Edit 2
Sorry, I forgot to mention that I'm actually trying to use {{currentUser.name}} from a partial ({{partial 'sidebar'}}), but that shouldn't change anything, because that's the same scope, right?
Edit 3
I noticed something very strange. When I call {{currentUser.name}} in my application template (which is not what I want btw), then it also works in the {{partial 'sidebar'}}.
Edit 4
As per request:
DEBUG: Ember.VERSION : 1.0.0-rc.6 ember.js?body=1:361
DEBUG: Handlebars.VERSION : 1.0.0-rc.4 ember.js?body=1:361
DEBUG: jQuery.VERSION : 1.10.0
This isn't the correct place to put this logic. You can use the route hooks model and afterModel on the ApplicationRoute, to do this easily. In general in ember loading of data is done in the routes hooks. This allows the router pause while loading so by the time your controller and templates come into play, they are working with loaded data.
App.ApplicationRoute = function() {
model: function() {
return App.User.findCurrent();
},
afterModel: function(model) {
App.set('currentUser', model)
}
}

How do I make an 'a' tag with a mailto href and bindAttr to a property?

I have a model, with a property 'contact_email'. I'd like to make a link with a mailto: href.
I've tried doing the slightly obvious <a {{bindAttr href="contact_email"}}>Email</a> but of course this is does not have the mailto: bit.
How can I combine mailto: with the property contact_email?
At the moment, the only workable approach is to use a computed property (as you described in your comment).
One thing that might make this more tolerable, if you find yourself doing this often, is to create a computed property "macro":
App.computed.mailto = function(property) {
return function() {
return "mailto:" + this.get(property);
}.property(property);
};
Then you could do this in your controller:
var mailto = App.computed.mailto;
App.UserController = Ember.ObjectController.extend({
mailtoContactEmail: mailto('contactEmail')
});
Register a simple bounded Ember Handlebars helper (Em.Handlebars.registerBoundHelper)
Em.Handlebars.registerBoundHelper('mailTo', function (emailAddress, label) {
emailAddress = Em.Handlebars.Utils.escapeExpression(emailAddress);
label = (arguments.length == 2) ? emailAddress : Em.Handlebars.Utils.escapeExpression(label);
var link = '' + label + '';
return new Em.Handlebars.SafeString(link);
});
And use it like this:
simple mailto link:
{{mailTo emailAddress}}
(output: foobar#example.com)
mailto link with alternate label
{{mailTo emailAddress username}}
(output: foobar)
Model used:
App.User = DS.Model.extend({
username: DS.attr('string'),
emailAddress: DS.attr('string')
});
Both values (the email address as well as the optional alternate label) are bounded to the model, and will change whenever the model changes.
Created a JSFiddle to demonstrate the changing model: http://jsfiddle.net/We6B9/
In the latest version of ember cli, you could do it like this:
In your view:
export default Ember.View.extend({
layoutName: 'layouts/legal',
templateName: 'views/legal/tou',
tagName: 'main',
classNames: 'view-legal-wrapper',
varViewTitle: 'Terms and Conditions',
varCompanySupportEmail: 'test#gmail.com'
});
In your handlebars template:
{{view.varCompanySupportEmail}}
Current setup at the time of this post:
DEBUG: -------------------------------
DEBUG: Ember : 1.5.1
DEBUG: Ember Data : 1.0.0-beta.7+canary.b45e23ba
DEBUG: Handlebars : 1.3.0
DEBUG: jQuery : 2.1.1
DEBUG: -------------------------------
Using a Handlebar Helper can be generic solution to the problem for all such use cases
Check the fiddle http://jsfiddle.net/devilankur18/YgLRb/1/
var getBindingValue = function(context, options, path) {
var normalized = Ember.Handlebars.normalizePath(null, path, options.data),
thisContext;
if (normalized.isKeyword) {
thisContext = normalized.root;
} else if (!Ember.isGlobalPath(path)) {
thisContext = context;
} else {
thisContext = null;
}
return Em.Handlebars.get(thisContext, normalized.path);
};
Handlebars.registerHelper('mail_to', function(context, options) {
var value = getBindingValue(this, options, context);
return 'href=mailto:' + value
});
var App = Ember.Application.create();
App.ApplicationController = Ember.Controller.extend({ email: "test#somthing.com" });
App.Router = Ember.Router.extend({
enableLogging: true,
root: Ember.Route.extend({
index: Ember.Route.extend({
route: '/'
})
})
});
I just managed to do this using emblem as follows:
a href="mailto:{{unbound email}}" Email
Which means you should be able to do something like:
Email
Try the concat helper:
<a href={{concat "mailto:" model.emailAddress}}>{{model.emailAddress}}</a>

Ember Router rootURL option (Uncaught Error: No route matched the URL '/admin')

I'm trying to start to build a admin system that will run on a /admin/ prefix.
Here is my routes file
App.Router.reopen
location: 'history'
rootURL: '/admin'
App.IndexRoute = Ember.Route.extend
setupController: (controller, model) ->
#controllerFor('application').set('currentRoute', 'home')
When I go to /admin I get the following error:
Uncaught Error: No route matched the URL '/admin'
I'm just starting with emberjs, and my code is based on this serie
Ember version: v1.0.0-pre.4
Ember-data current api revision:: 11
In old-router the 'rootURL' property would have been ignored when resolving routes. In the latest version of ember, rootURL only seems to be used when constructing links. Not sure if this is a bug or oversight. As a workaround, try this instead:
App.Router.map(function() {
this.resource("admin", { path: "/admin" }, function() {
this.route("other");
});
});
App.IndexRoute = Ember.Route.extend({
redirect: function() {
this.transitionTo('admin');
}
});
When talking about routing in emberjs, it depends which version you are using. There was a big API change between 1.0pre2 and 1.0pre3. The docu on www.emberjs.com is already up-to-date for the new API and and easy to understand.
Below a really small example that shows
IndexRoute that automatically redirects to the overview of all members at '/members'.
Dynamic routing based on an ID
Serialization/Deserialization in case that the parameter is not 'id' but something else. In the example below, it is 'refId' (stands for reference ID).
Well, the examle does not really show more than the official documentation. but add-on information is always nice.
So, hope this helps. cheers.
App.Router.map(function() {
this.resource("members", { path: '/members' });
this.resource("member", { path: "/members/:refId" }, function() {
this.route("delete");
});
});
App.IndexRoute = Ember.Route.extend({
redirect: function() {
this.transitionTo('members');
}
});
App.MembersRoute = Ember.Route.extend({
model: function() {
return App.Member.findAll();
}
});
App.MemberRoute = Ember.Route.extend({
model: function(params) {
return App.Member.find(params.refId);
},
// overwrite default serializer (defaults to 'id', member has 'refId')
serialize: function(model) {
return { refId: model.refId };
}
});