I am using the ember-select-2 component from https://github.com/iStefo/ember-select-2 in my Ember.js project. The list of items is fairly simple and is loaded using Ember data in the route:
setupController: function(controller, model) {
this._super(controller, model);
var otherModelsPromises = {
accomodationTypes: this.store.find('accomodation-type'),
};
Ember.RSVP.hash(otherModelsPromises).then(function(results) {
controller.set('accomodationTypes', results.accomodationTypes.get('content'));
});
And in my template, I have:
{{select-2 placeholder="Filter By" content=accomodationTypes cssClass="search-filter-dropdown"}}
And here is the JSON being returned from the URL (http://localhost:4200/api/accomodationTypes)
{"accomodationTypes":[{"id":1,"text":"Bed & Breakfast","description":"","svgid":""},
{"id":2,"text":"Self Catering","description":"","svgid":""},
{"id":3,"text":"Hotel","description":"","svgid":""},
{"id":4,"text":"Boutique Hotel","description":"","svgid":""}]}
I can see the promise being eventually resolved in route and data being returned properly. However, when I try and click on the select2 control, I get the following error in console:
Uncaught Error: Assertion Failed: select2 has no content!
If I use a static data in the controller, it works. I have a feeling that because the promise is not resolved by the time the select2 component is rendered, it fails? And it seems like the content variable is not set to use promises?
I could try and use a query, but I do not want a type ahead lookup. I just want to display a simple dropdown with multiple options and option to delete.
Am I missing something or is this a bug?
Edit: Here is the model that I'm using (models/accomodation-type.js)
import DS from 'ember-data';
export default DS.Model.extend({
text: DS.attr('string'),
description: DS.attr('string'),
svgid:DS.attr('string'),
});
Bah..I figured it out. I was doing the following two this wrong:
1. Turns out that setupController is called after the view has been rendered so the view won't have access to data when it gets rendered. So, corrected by returning a promise from model hook. This will keep the view from rendering until the models are resolved.
import Ember from 'ember';
import DS from 'ember-data';
export default Ember.Route.extend({
model: function(params) {
return Ember.RSVP.hash({
listings: this.store.find('listing', params),
accomodationTypes: this.store.find('accomodation-type')
});
},
});
Changed the select-2 component in the template to use the below:
{{select-2 placeholder="Filter by" searchEnabled=true allowClear=true multiple=true content=model.accomodationTypes cssClass="search-filter-dropdown"}}
And it works like a charm!
Related
Pretty new to Ember so maybe someone can help me out. I keep running across this error and have no idea how to solve it.
Ember : 2.5.1
Ember Data : 2.5.3
Below is my router.js.
//app/router.js
import Ember from 'ember';
import config from './config/environment';
const Router = Ember.Router.extend({
location: config.locationType
});
Router.map(function() {
this.route('organization', {path: '/organization/:id'}, function(){
this.route('about', { path: '/about' });
this.route('admin', { path: '/admin' }, function(){
this.route('team', { path: '/team/:team_id' });
});
});
});
The organization/:id/about and organization/:id/admin routes work fine. But when I try to load the organization/:id/admin/team/:team_id route, the error is thrown. Below is the routes/organization/admin/team.js file:
//app/routes/organization/admin/team.js
import Ember from 'ember';
export default Ember.Route.extend({
model(params) {
let organization = this.modelFor('organization');
return organization.get('team');
}
});
Not really sure what other information I should post, so please ask for any additional information you may think is necessary to help debug. My guess is it's something pretty simple and I'm completely oblivious to it.
EDIT
I've added a couple more files to help diagnose the problem:
//app/routes/organization.js
import Ember from 'ember';
export default Ember.Route.extend({
model(params) {
return this.store.findRecord('organization', params.organization_id)
}
});
//app/routes/organization/admin.js
import Ember from 'ember';
export default Ember.Route.extend({
actions: {
changeValue(){
this.currentModel.save();
}
}
});
Where currentModel is the model for the organization route. I've removed the organization.admin.team model hook for now and am just testing a
{{#link-to 'organization.admin.team' model.team.id}} Team {{/link-to}}
in a component rendered in the organization.admin template where I pass model=model. But now I get the same error (Assertion Failed: You need to pass a model name to the store's modelFor method) in the Javascript console when rendering the organization.admin template.
If you pass Object to {{#link-to}} helper. It skips the model hook. So you could basically send {{#link-to 'team' organization.team}}Without having to write "model" hook.
"It makes sense and it might save a request to the server but it is, admittedly, not intuitive. An ingenious way around that is to pass in, not the object itself, but its id" - https://www.toptal.com/emberjs/the-8-most-common-ember-js-developer-mistakes".
So you should do
hbs
{{#link-to 'team' organization.team.id}} Link to team management {{/link-to}}
route
model(params) {
return this.store.findRecord('team', params.team_id)
}
you can use modelFor('parent') method to get organization model.
like that
//app/routes/organization/admin/team.js
import Ember from 'ember';
export default Ember.Route.extend({
model(params) {
let organization = this.modelFor('parent');
return this.store.findRecord('team', params.team_id)
}
});
i think you wants to do something like that.
basically ember does not support nested routes.
I have a route in ember which looks like
//fish.js
import Ember from 'ember';
export default Ember.Route.extend({
model: function(params) {
return Ember.RSVP.hash({
fishPrices: this.store.query('fish-price', {filter: {type: params.type}}),
type: params.type
});
}
});
My fish.hbs uses model.type to change text on the page. However, I need to hand model.fishPrices off to a component which plots the price of the fish as a function of time:
//fish-price-plot.js
import Ember from 'ember';
/* global Plotly */
export default Ember.Component.extend({
didInsertElement() {
console.log(this.get('model'));
Plotly.plot( 'fish-price-plot', [{
// ...
//Need to access model.fishPrices here
}
});
How do I access the model in this component? I see a lot of information that suggests that I should be able to do something like
var fishPrices = this.get('model.fishPrices');
//do something with fishPrices
but this always ends up undefined.
One way is directly passing it to the component props like this:
// route template in which you want to use your component & model
{{fishprice-plot model=model}}
Have a look at the following twiddle that demo's the first use case.
The other is injecting a service into the component with the required data.
// components/fishprice-plot.js
export default Ember.Component.extend({
fishData: Ember.inject.service()
});
Have a look at this twiddle that demonstrates passing data to a component more comprehensively, and also this part of the guides, as pointed out by #locks in comments.
You can also have a look at this SO link regarding passing properties to your component.
I'm trying to set queryParams in an Ember controller, but they don't seem to be updating the URL at all.
I have this abbreviated mixin being applied to the route:
import Ember from 'ember';
import ControllerPaginationMixin from './controller-pagination';
export default Ember.Mixin.create({
setupController(controller, model) {
this._super(controller, model);
controller.reopen(ControllerPaginationMixin);
}
});
And here's the abbreviated controller mixin that is applied above:
import Ember from 'ember';
export default Ember.Mixin.create({
sortKey: null,
queryParams: ['sortKey'],
actions: {
sort(key) {
this.set('sortKey', key);
}
});
When I call the sort method from a component, I can see in the Ember Inspector that the sortKey property has been changed to the correct new value, but the URL remains unchanged. Am I missing something?
Your problem is that you're trying to customize the controller class at the runtime.
You will reopen the controller every time a user visits the route, that's ridiculous.
Simply extend the controller definition with the mixin and you're good to go.
I have a scenario where there are "jobaids" - jobaids belong to "businessunits", "systemapplications", and "courses" & finally "businessunits" have many of all of the above.
When entering the project you start on the "businessunits" route (#/businessunits), where they are listed as "#link-to"s they link to a show view and when clicked move you to #/businessunits/:businessunits_id
When you arrive on this template there is a an option to view the current "Businessunit"s related "Jobaids" by "systemapplication", "course" or just "show all"
Since the easiest place to start in consideration of the model relationships (and because I'm new with ember), is the "show all" option, and that's where I've started.
So - what I need to do is get the :businessunit_id in...
#/businessunit/:businessunit_id
to be seen by the processing in the
#businessunit/:businessunit_id/jobaids
...to be able to apply to that route, a model consisting of something like
this.store.find('jobaid', {businessunit_id: ID-FROM-PARENT-ROUTE})
so far I have...
/app/router.js
import Ember from 'ember';
import config from './config/environment';
var Router = Ember.Router.extend({
location: config.locationType
});
Router.map(function() {
this.resource("businessunits", function() {
this.route("show", { path: ":businessunit_id" }, function(){
this.resource("jobaids", function() {});
});
});
});
export default Router;
...and the "show all" link leading to the route where I need the value of the parent id is an actual anchor tag with an {{action "getJobaids"}} which is handled with the show in the /app/routes/businessunits.js route
import Ember from 'ember';
export default Ember.Route.extend({
model: function(){
return this.store.find('businessunit');
},
actions: {
getJobaids: function(){
var url = location.href.split('/');
window.unitClicked = url[url.length-1];
this.transitionTo('jobaids');
}
}
});
then when you get to /app/routes/jobaids.js we're getting the needed id from the window...
import Ember from 'ember';
export default Ember.Route.extend({
model: function(){
return this.store.find('jobaid', {businessunit_id: unitClicked});
}
});
this is TERRIBLE but this works enough to get me to the next route (where there are some other problems I have yet to figure out relating to querying the fixture and or adapter) - HOWEVER this is NOT a desirable fix and will never keep state, basically eventually resulting in missing (necessary) variables when linking back
#/businessunits/undefined/jobaids
which as you can imagine breaks everything - so how do I do this in the genuine ember fashion without depending on a hacky use of bare bones js?
I ended up taking the development of this project in the direction of having an actual database back end to query against and let the relationships in ember's data library handle the nested object structure to access the relations returned in the JSON structure.
In 1.7 Ember should support Query Parameters. I have no problems using them in controller but I'd like to access them in Route, ideally in beforeModel hook but model hook would work as well.
The API docs mention a queryParam parameter for the beforeModel hook but if I try to use it, it is always undefined.
The Query Parameters guide seems to suggest that the query parameters should be accessible as a part of the first parameter to the model hook. But that is also undefined. See the code below for examples.
Is there a way to access the query parameters from Route?
Thank you for your help.
App.ApplicationRoute = Em.Route.extend({
beforeModel: function(transition, queryParams){
console.log(queryParams.test); //undefined at /?test=123
},
model: function(params){
console.log(params.test); //undefined at /?test=123
}
});
Pretty sure it's a bug, but you can access them in the meantime via the transition object:
App.ApplicationRoute = Em.Route.extend({
beforeModel: function(transition){
console.log(transition.queryParams.test);
}
}
By specifying the query params in the controller, params will contain them automatically
ApplicationController = Ember.Controller.extend({
queryParams: ['test'],
test: null
});
In the latest version of ember (2.12 at the time of writing this answer), queryParams can be accessed in the model hook as follows:
import Ember from 'ember';
export default Ember.Route.extend({
queryParams: {
test: ''
},
model(params) {
console.log(params.test);
},
});
Observe that now both dynamic segment and queryParams are accessible via the params object. Since params is not available in the beforeModel hook, this solution works on when you have to access the queryParams in the model hook.
In latest ember version you can get the value in Route as
import Ember from 'ember';
export default Ember.Route.extend({
beforeModel(params){
console.log(params.queryParams.test); //if the parameter contains test as the key
}
});
This works only if the locationType is auto in your environment.js file.
If you want to access in didTransition action,
didTransition: (queryParams) ->
console.log(#get('queryParams'))