EmberJS transitionTo firstObject for async hasMany - javascript

I want to redirect users to the route for the firstObject of a collection when they arrive at the containing object.
A container hasMany items, currently in the ContainerRoute.afterModel I am doing:
this.transitionTo('container.item.index', model, model.get('items').get('firstObject'));
Which is fine when the items are not async.
The problem is the firstObject isn't a promise so the route/transition doesn't pause.
Here is the model hook:
return this.get('store').find('container', params.containerId);
What's the cleanest approach? The options I see are:
change the model hook to populate the
build and pass a promise as the parameter to transitionTo
transitionTo the ID of the object instead of the object (writing a solution for this now)

transitionTo can take an object (actual or promise), or an ID.
I opted to just send the ID in the ContainerRoute:
this.transitionTo('container.item.index', model, model.get('firstItemId'));
You can get the ID without inflating the object by accessing:
this.get('data.submissions.firstObject.id');
Which was borrowed from a github issue about avoiding loadMany

The hasMany property is a promise like object, so you can use the then method, to know when it't is resolved:
model.get('items').then(function(items) {
this.transitionTo('container.item.index', model, items.get('firstObject'));
});

Related

Looping over an Ember.js promise

I am trying to loop over what I believe to be an Ember promise, but all I can seem to get returned is an object, when it should be an array.
jsbin: http://emberjs.jsbin.com/qakine/1/edit
If I just loop over the items in the template then I have no issues, but I want to be able to interact with the array items in my controller. Any help appreciated.
Quite a few things here, let me see if I can remember them all:
When you have a route under a resource, the routes and controllers of that route should take their parent's name.
App.Router.map(function() {
this.resource("parent", function(){
this.route("child");
});
});
App.ParentChildRoute...
App.ParentChildController...
Handlebars can't access normal functions from your controller, this should be converted into a computed property.
App.ParentChildController = Ember.ObjectController.extend({
middleNames: function(){
...
}.property('middles.[]')
});
naming is case sensitive
{{#each name in middlenames}}
should be
{{#each name in middleNames}}
Example: http://emberjs.jsbin.com/cowibi/1/edit
I created an new example based on yours to make things clear. You can check it out here:
http://emberjs.jsbin.com/hokabe/4/edit
For Ember route's model hook, if the return value is a promise, the route will wait for the promise resolved and pass the resolved value to controller's model property.
And a App.Parent instance's middles property returns a promise (actually it's a DS.PromiseArray instance) which will resolve a middles array (actually it's a DS.ManyArray instance).
so for getting children you can simply do this:
App.ParentMiddlesRoute = Ember.Route.extend({
model: function() {
return this.modelFor('parent').get('middles');
}
});
Note that modelFor argument is a route name but not a model name. It means "Get the model from given route".

In Sails.js lifecycle callback, how can I programmatically determine the model name?

I have two models, one that extends from the other.
I want to define a lifecycle callback in BaseObject that all of the sub-models can inherit. But I don't know to get the name of the model being acted on inside the callback. Some of the sub-models will need this info. e.g.,
{
beforeCreate: function (model, next) {
// I want to know the model's identity in here
}
}
model is just a straight key/value list of the model's attributes, but it does not contain any schema information, such as the model's name. this seems to just point to global. I have access to the global sails object, but I don't know how to determine what this model is.
I ended up building this feature. I don't think it was possible before.
https://github.com/balderdashy/waterline/pull/611

Ember: transition to route passing the ID instead of obj

I have some route like /ads/:ad_id and from my controller I can do
this.transitionToRoute('ads.ad', adObj)
How can I do the similar thing but this time passing the ID instead of the loaded object?
O course I understand that I can load an obj by ID first, but Ember's power is in doing lost of boilerplate for us.
Update: So, as by default Ember serializes the model to URL params by doing like
mode_instance -> { model_name_id: model_instance.id }
My trivial attempt was doing
this.transitionToRoute('ads.ad', { id: adObjId })
But when passed a model object Ember does not re-fetch it.
So, the question: I have a route (single ad view) that depends on ad ID. I have this ID as number. I want to transition to this route like if I simply entered the url /ads/ID
This can be accomplish by passing the URL to transitionTo. For example,
this.transitionToRoute('/ads/' + adObjId)
The model() method will be called with the params from the URL.
Here is a use case for this:
Transitioning from a list view to a detail view. In the list view, the records don't have any relations tied to them, but the detailed view should side-load relational data. For this reason, the models are not 1:1 between the list view and detailed view. There should be a way to transition simply using the id.
Cp
What's your use case for this? Most cases when you would want to specify an object by id, you already have the object to pass to transitionTo. Can you provide more context about what you're trying to do? I think you can probably accomplish it without using the object id.
In any case, I don't think there's a good way to do this, because when you transition via transitionTo(someRoute, someModel), the route's model hook is not called, and the model you pass in (someModel) is supplied directly to the other route hooks (setupController(controller, model), redirect(model), renderTemplate(controller, model)).
See Ember.JS Route api -- model method for more details.

Backbone state handling with nested models?

I'd like to manage all hash state attributes (#) in one Backbone model.
StateModel //Pseudo
attributes
layout : string
modelType1 : model
modelType2 : model
This way I could consistently update history entries just by serializing this single model.
HistoryController
StateModel.bind("change", this.updateHistory);
[...]
state = StateModel.toJSON()
[...]
appRouter.navigate('v1' + state, false);
How do I make the HistoryController trigger change when the nested models (in the StateController) change?
And if the hash changes - and I'd like to update my StateModel - how do these changes propagate down to the nested models? (without causing a feedback loop)
Nested models in Backbone can be tricky because the getter and setter methods do not have built-in functionality to operate at depth. However, I have found that the best way to handle this is to store Backbone models inside other Backbone models. In your example, you would instantiate StateModel and then set its modelType1 and 2 to be, say, TypeModel instances. You can then stateModel.get("modelType1").bind("change",this.updateHistory) and stateModel.get("modelType2").bind("change",this.updateHistory). Alternatively, if you are going to be creating a lot of TypeModels, you can put this binding in the initializer function.
Secondly, you can stateModel.get("modelType1").bind("change",stateModelInstance.updateFoo) or whatever method you would like to call when the modelType model changes.
The nice thing about this pattern is that if you need stateModel to change one of the modelType models you can do stateModel.set({modelType1:newModel3}) or something of that ilk. If you have set the binding action in the ininitializer of TypeModel, everything will stay synced up. If you don't want to blow out the nested model on a change, just do stateModel.get("nestedModel1").set({"foo"}:"bar"). This shouldn't cause a feedback loop unless you have bound something to your stateModel change action that changes the nested Model again but I don't know why you would do that.

Implementing Backbone.Subset.js in Backbone.js to filter Models from a parent Collection

In this stackoverflow post i read about filtering backbone collections and using subsets.
One answer (by sled) recommends using backbone.subset.js (usage example).
I could not find any further resources on backbone.subset.js and I failed implementing it into my project.
It seems like backbone.subset.js is the perfect solution for what i'm trying to achieve.
(Having one "parent" collection that holds all models at all times, and depending on user input filtering the relevant models from the parent collection into a backbone.subset collection.)
My "parent" collection, holding all tasks:
var TasksAll = Backbone.Collection.extend({
url: '/tasks', // the REST url to retrieve collection data
model: Task // the models of which the collection consists of
});
var allTasks = new TasksAll();
Now i want to create a subset collection for e.g. tasks where task.status = 0:
var TasksTrash = new Backbone.Subset({
superset: allTasks,
filter: function(Task) {
return Task.isTrash();
}
});
var trashTasks = new TasksTrash();
Whereas inside the Task model, the method "isTrash" returns true if:
this.get('status') == 0
a) Are there any more resources on backbone.subset.js?
b) How do I implement above scenario?
c) Can I pass 'superset' and 'filter' options as params to the Backbone.Subset init function?
d) I looked into the backbone.subset.js code, when I 'reset' my parent Collection my subset Collections should be updated straight away, right?
PS: I'm fairly new to Backbone. Thanks for your help.
Looking at the source for backbone-subset, it looks as though there is a pre-initialization hook which you could utilize in order to make the 'sieve' or filter available as an option or argument:
https://github.com/masylum/Backbone.Subset/blob/master/backbone.subset.js#L50
As for providing parent as an argument, there is an outstanding patch to add that exact functionality:
https://github.com/masylum/Backbone.Subset/pull/5
With it, you can pass in parent as an option, if it is not an option the library will fall back to looking for it on the object Prototype

Categories

Resources