Access Query Params in view or in view's controller - ember.js

so in the users/confirmation route, I am able to access that confirmation_token in the setupController hook
export default Ember.Route.extend(PresentsModalsMixin, {
setupController: function(controller, model){
this._super(controller,model);
controller.get('confirmation_token'); // token I want in query params is available here.
}
});
but in the view the confirmation token is no longer at this.get('controller.confirmation_token'')
export default Ember.View.extend({
templateName: 'users/confirmation',
actions: {
submit: function() {
this.get('controller.confirmation_token'); // null
this.get('controller').send('submit');
}
}
}
});
in the controller where the action goes, it is also no longer available
export default Ember.Controller.extend({
queryParams: ["confirmation_token"],
confirmation_token: null,
actions: {
submit: function() {
this.get('confirmation_token'); // null value
}
}
});
why is the query param getting blown away? and is there a way I can get it back
the template that is calling the view looks like this
{{render 'users/confirmation' currentUser}}

the correct answer is
{{render 'users/confirmation'}}
removing currentUser as the second argument and not passing any argument fixes this issue and allows you to keep the query params, it gets overwritten when you pass a second argument like this
{{render 'users/confirmation' currentUser}}

Related

ember.js have view's function observes controller's property

I have written a view:
export default Ember.View.extend({
select: null,
modify: null,
createSelect: function() {
return new ol.interaction.Select();
},
onMapCreated: function() {
this.select = this.createSelect();
this.modify = this.createModify();
},
init: function() {
this._super();
this.get('controller').addObserver('olMap', this.onMapCreated);
},
});
The view is added in a template related to a controller which has an olMap property.
I need to wait for the olMap property to be instantiated before doing some work in my view.
The code above is kind of working, except that the this referenced in the onMapCreated function is the controller's instance and not the view's instance.
I'm quite sure I am doing something wrong in my application's design. I would like to separate the concerns and get the drawing part outside of the main controller. Should I use a component? Not sure because it's not going to be reusable...
I would love to have some directions here.
After reading the manual in the API section, I came up with the solution. I post it here is someone needs it someday. Actually, all I had to do is add a parameter this to the addObserver method in order to change the context.
export default Ember.View.extend({
select: null,
modify: null,
createSelect: function() {
return new ol.interaction.Select();
},
onMapCreated: function() {
this.select = this.createSelect();
this.modify = this.createModify();
},
init: function() {
this._super();
this.get('controller').addObserver('olMap', this, this.onMapCreated);
},
});
Here is what I've ended up with:
My setup:
Ember : 1.10.0
Ember Data : 1.0.0-beta.16
jQuery : 1.11.2
Directory structure:
controllers:
map.js
map-draw.js
templates
map.hbs
map-draw.hbs
views
map.js
map-draw.js
in the template templates/map.js I use a render helper like this:
{{render "mapDraw" mapDraw}}
the renderer uses the controller controllers/map-draw.js and the view views/map-draw.js
content of the view map-draw.js:
export default Ember.View.extend({
templateName: "mapDraw",
classNames: ["map-draw"]
});
in the controller map-draw.js I am binding the map.js controller.
export default Ember.Controller.extend({
needs: ['map'],
olMap: null,
//...//
init: function() {
this._super();
this.get('controllers.map').addObserver('olMap', this, function(sender) {
this.set('olMap', sender.get('olMap'));
});
}
//...//
});

Ember Select component rendering before promise is resolved

I have a component which adds some functionality to a <select> tag. I want to initialise some javascript after the <select> has fully rendered including all <option> tags. The data used to populate the <option> tags is an array of objects provided from an ajax request.
I'm using ember-data and finding this works when the data is provided from the store, meaning it is an instance of DS.RecordArray which has helpful properties like isLoaded. However, when the data is provided from a jQuery ajax call and is just plain JSON, it appears as though the component tries to render everything before the promise returned by jQuery is fulfilled.
I feel the issue is with how I'm handling promises as the issue seems to be related to things initialising before they should (ie promises have resolved properly). I tried wrapping the ajax call in an RSVP.Promise object but not luck, (I'm using Ember-CLI). Below is a simplified version of what I have so far. Any help would be appreciated.
// My route
export default Ember.Route.extend({
setupController: function(controller, model) {
this._super(controller, model);
var hash = Ember.RSVP.hash({
// myOptions: $.getJSON('/api/options')
myOptions: new Ember.RSVP.Promise(function(resolve, reject) {
Ember.$.ajax({
url: '/api/options',
type: 'get',
dataType: 'json',
success: function(result) {
Ember.run(null, resolve, result);
},
error: function(result) {
Ember.run(null, reject, result);
}
});
})
});
return hash.then(function(result) {
controller.set('optionsForSelect', result.myOptions);
});
}
});
// My component
export default Ember.Select.extend({
didInsertElement: function() {
// Is called before ajax request has finished
this.$().mySelectPlugin({
});
}
});
// Handlebars template
{{my-select-plugin content=optionsForSelect optionValuPath="content.id" optionLabelPath="content.name"}}
To me, this seems like something that should be handled in the controller, not the route. Here's what I did for a similar situation.
App.LessonsShowIndexController = Ember.ObjectController.extend({
author: function() {
return this.get('model').get('author');
}.property('author'),
fullName: function() {
return this.get('author').get('firstName') + ' ' + this.get('author').get('lastName');
}.property('author.isFulfilled'),
});
Using the isFulfilled property allows the controller to wait for the promise to resolve before using the data. In your case, you could have a property that returns a promise and another that waits for it to be fulfilled.

Ember v1.6.0beta is removing the query string from the URL - Cannot get queryParam

Ember seems to be removing the query string from the URL.
I've stepped through the code, and I know for sure that I'm setting the flag correctly:
<script>
ENV = {FEATURES: {'query-params-new': true}};
</script>
<script src="js/libs/ember.prod-1.6.0beta+canary.js"></script>
But when my route loads, the query string is being removed, and I can't access the queryParams.
Here's my router:
App.Router.map(function () {
this.resource('simpleSearch', {path: 'simplesearch'}, function () {
this.resource('simpleSearchOption', {path: ':simpleSearchOption_id'});
this.resource('simpleSearchResults', {path: 'results'});
});
});
When I attempt the following url (which is based on the URL from the guide), the query string is stripped: [webserver]/#/simplesearch/0?simplesearch[height]=10
When the model is first initialized by the route, it builds out what the query parameters will be, and the controller's queryParams property is set by the route:
App.SimpleSearchRoute = Ember.Route.extend({
model: function () {
var optionsForSimpleSearchModel = [];
for (var i = 0; i < App.SimpleSearchOptions.length; i++) {
optionsForSimpleSearchModel[i] = App.SimpleSearchOption.create(App.SimpleSearchOptions[i]);
}
return App.SimpleSearch.create({
'simpleSearchOptions': optionsForSimpleSearchModel,
'numOfOptions': App.SimpleSearchOptions.length
});
},
setupController: function (controller, model) {
console.log(model.get('queryParams'));
controller.set('queryParams', model.get('queryParams'));
controller.set('model', model);
}
});
BUT, I've also tried explicitly setting the queryParams in the controller:
App.SimpleSearchController = Ember.ObjectController.extend({
height: null,
queryParams: ['height'],
...
I'm not sure what else I'm missing...
How does this thing really work?
It seems that I'm a silly dude.
I needed to add the params argument to the model() function:
model: function (params) {
console.log(params);
//{height: null} when queryParams['height'] is explicitly set in the controller
Is there any way that I can dynamically generate the queryParams for the controller before Ember decides there are none, if I don't set them explicitly?
Also, my URL was incorrect, (as is the one in the Ember guide). It should have been:
[webserver]/#/simplesearch/0?height=10
instead of
[webserver]/#/simplesearch/0?simplesearch[height]=10
In your model hook you need to pass in the params.
App.SimpleSearchRoute = Ember.Route.extend({
model: function (params) {
return this.store.findQuery('simpleSearch', params);
}
});
Here is another question along the same lines.
Cheers

Using Ember data's find in route setupController in Ember 1.0.0

[I'm on Ember 1.0.0 - Ember.data 0.13]
In a nested route I'm using the setupController hook in order to load a list of templates which I use as selection list for my model, a Offer object:
controller.set('offerTemplates', App.OfferTemplate.find());
Complete code:
App.OfferEditRoute = Ember.Route.extend({
model: function () {
return this.modelFor("offer");
},
setupController: function (controller, model) {
controller.set('content', model);
controller.set('offerTemplates', App.OfferTemplate.find());
},
renderTemplate: function () {
this.render('offer-edit-title', { into: 'application', outlet: 'page-title', controller: 'offerEdit' });
this.render('offer-edit', { into: 'application', controller: "offerEdit" }); //
}
});
App.OfferEditController = Ember.ObjectController.extend({
offerTemplates: [],
...
)};
This used to work until Ember 1 RC 7, but doesn't in 1.0.0. The main content of the Offer (model) is correctly rendered, but the template list bound to the controller's offerTemplates property (array) is not rendered on loading the page (browser page refresh).
If I switch page and back to the route, all is rendered correctly.
Any hint?
The problem was related to the template which doesn't use the offerTemplates array but a computed property offerTemplatesByGuestUserLanguage:
{{#each offerTemplate in offerTemplatesByGuestUserLanguage}}
...
{{/each}}
I forgot the second to add the second property content.guestUser.language in the computed property of the controller:
offerTemplatesByGuestUserLanguage: function() {
var templates = this.get("offerTemplates"),
guestUserLanguageCode = this.get("content.guestUser.language.code");
return templates.filter(function (item) {
return item.get("language.code") === guestUserLanguageCode;
});
}.property('offerTemplates.#each', 'content.guestUser.language')
I wonder why it even worked in RC.7.

Ember js pre 4 - router not resolving id on link click

I have a list of accounts and then i have a view link to view an account in detail and this is the account route. When i click the view link the (guid) doesnt update when going through the router, it only updates in the URL but it doesnt seem to be carrying through to the code.
When i do a browser refresh then the (guid) gets carried through to the router... Its not resolving for some reason.
Im not using ember-data but will use it in the future.
Here is my "Accounts" template code with the "View" link:
{{#each accountdata in controller}}
<tr>
<td>{{accountdata.accountnumber}}</td>
<td>{{accountdata.accountname}}</td>
<td>{{accountdata.accounttypestatus}}</td>
<td>{{accountdata.accountuser}}</td>
<td>{{#linkTo account accountdata}}View{{/linkTo}}</td>
</tr>
{{/each}}
accountdata is the context with the "accountguid" which is my id.
Here is my router:
App.Router.map(function() {
this.resource("accounts", { path: '/accounts' });
this.resource("account", { path: "/accounts/:accountguid" });
});
App.AccountsRoute = Ember.Route.extend({
setupController: function(controller, model) {
controller.set('searchfilter','ALL');
controller.search();
}
});
App.AccountRoute = Ember.Route.extend({
setupController: function(controller, model) {
controller.show(controller);
},
model: function(params) {
this.controllerFor('account').set('accountguid',params.accountguid);
},
serialize: function(model) {
return {accountguid: Em.get(model, 'accountguid')}
}
});
My controller.show is where i send the context to call a script to display the account details.
So i just need view to carry through the correct accountguid each time which it isnt and then to call the show(context) method.
Thanks
This is my old router code which worked 100%. When i clicked a link it resolved the :accountguid and when i did a browser refresh it did the same thing. i had no problems, everything just worked.
// //Accounts
// accounts: Ember.Route.extend({
// route: '/accounts',
// index: Ember.Route.extend({
// route: '/',
// connectOutlets: function (router) {
// router.get('applicationController').connectOutlet('accounts');
// router.get('accountsController').set('searchfilter','ALL');
// router.get('accountsController').search();
// }
// }),
// view: Ember.Route.extend({
// route: '/:accountguid',
// connectOutlets: function (router, account) {
// router.get('applicationController').connectOutlet('account', account);
// router.get('accountController').show(account);
// //router.get('accountController').connectOutlet('eventloghistory','eventloghistory');
// }
// })
// }),
I managed to solve my problem with the following code. I am now able to refresh the browser and i am able to click the link and it will carry through the current :accountguid in use to the show() method.
App.AccountRoute = Ember.Route.extend({
model: function(params) {
return {accountguid: params.accountguid};
},
setupController: function(controller, model) {
controller.show(model);
},
serialize: function(model) {
return {accountguid: Em.get(model, 'accountguid')}
}
});
Change your router map to the following and it should work
App.Router.map(function() {
this.resource("accounts", function(){
this.resource('account',{path:':account_id'});
});
});
Please, show us the code behind your AccountsController and AccountController. It would be most useful if you provide a jsfiddle with the whole construction.
In general, you may be unaware of the new flow of things. Here is what happens in the two scenarios:
1. You navigate to the AccountRoute by setting the URL (/account/5 for example).
1.1. the 'model' hook of the AccountRoute is called
model: function(params) {
return your model here...
}
with params = { accountguid: 5 }. Because you are not using ember-data, you should implement this hook and initialise and return the model there.
1.2. the setupController hook is called with the AccountController and the model returned by the model hook. Without the code behind
controller.show(controller);
It is not quite clear what its purpose is, but you should probably do something like
setupController: function(controller, model) {
this._super(controller, model);
controller.set('content', model);
controller.show(model);
}
As you can see, by not implementing the model hook, you URL stays correct, but the route does not know how to build the needed model resource.
You transition to the route via a linkTo call
{{#linkTo account accountdata}}View{{/linkTo}}
Here, linkTo expects accountdata to be the full account model for the route. Meaning it may not carry only partial data like id for example (read this for clearance: In latest Ember, how do you link to a route with just the id/name of a model, rather than providing all of its attributes in the linking page?).
2.1. The model hook of the AccountRoute is NOT called. The AccountRoute model property is set to the object that is passed to linkTo instead (in our case 'accountdata').
2.2. setupController is called with AccountController and the accountdata object.
If you accountdata object is not complete, it would be wise to create a complete instance here and set it to the controller.
As you can imagine, if you accountdata is like { id: 5, accountname: "John", accounttypestatus: "A", ...}, then after a click on linkTo, the URL will update correctly to /account/5, but the account template will receive accountdata, rather than an actual account.
P.P. If none of the above is any help, this might be your issue: https://github.com/emberjs/ember.js/issues/1709