Is there a way to avoid a template destruction when changing routes in iron-router? Since my template is all reactive but a little bulky, I want to keep it "behind the scenes" (in memory) while going to other templates and just show it when the route come back without re-creating everything (it is builded through several mongo/minimongo collection queries that add delays to the user experience).
I can think in some workarounds like hide/show DOM objects (awful solution) or make my route a home route and nest all other routes inside (not so good) but I wonder if there is a native way to accomplish that.
Thanks in advance.
Related
i'm very confuse about how ember controller works.
I'm starting with ember and ember-cli now, and i would like to understand more about how controller works.
If i have an nested route called new, inside a events resource, i should i have:
models/event
routes/events/new
templates/events/new
What about controllers?? I just work one simple controller, or should i use controllers/events/new too?
There isn't any generator command that will create every resource for me? I need call one by one?
Thanks.
What about controllers?? I just work one simple controller, or should i use controllers/events/new too?
This mainly depends on what is your controller needs to do. If it's only the essential stuff the controller does anyways, Ember will create that controller under the hood for you and automatically bubble actions up to its parent controller.
No better place than Ember guides to read what a controller is used for:
The simplest definition is:
Controllers allow you to decorate your models with display logic.
This means that you basically use them as the main communication layer between your route and your template. Essentially, you model comes from your route, through your controller and into your template. Actions happening in the template go up to the controller and then to the route. Therefore, controller is essentially the middle layer where you user your model (and other data) to control what is shown to the user, control what a user can do, control where can they navigate etc.
However, be aware of the plan for the future:
Controllers are very much like components, so much so that in future versions of Ember, controllers will be replaced entirely with components. At the moment, components cannot be routed to, but when this changes, it will be recommended to replace all controllers with components.
This means, that right now, controller responsibility is limited to two things:
Maintaining application state based on the current route
Handling or bubbling user actions that pass through the controller layer when moving from a component to a route.
All actions triggered on a template are first looked up on the controller, if it is not handled or bubbled (by return true) in the controller, they are looked up on the route.
Therefore, controllers for your /events or events/new routes aren't necessary at all, only if you want to handle things happening on those routes right away (in a smaller scope) instead of allowing everything to bubble up to the ApplicationController.
There isn't any generator command that will create every resource for me? I need call one by one?
Yes. Since, if you don't specifically create a controller, Ember just generates one for you behind the scenes. You need to specify where you want to handle things yourself.
You should visit the link I gave above (or here it is again) to the Ember guides that have many more examples in much more detail.
I've been learning Ember over the past few months, and with the beta release of 2.0 I've working on following the "data down, actions up" structure with my components. Unfortunately, this means actions are getting thrown all over the place and it's not very appealing to define them in every component and every template, only to be like, "yes, keep bubbling this up to the controller please". Is there any way to pass actions in groups or nest them so that in my handlebars templates I can just use something like {{my-component myActionGroup=myActionGroup}} and then unpack them within the component definition? Or maybe a setting to tell ember to allow component actions to bubble?
The component I'm working on right now is for nested sets, so I'm ending up with really deeply nested components. Keeping them all straight is pretty awful and doesn't seem very DRY to me since changing the name of one requires changing the associated one in close to ten other files. I know I could just reroute one to another in the handlebars template but then they become a mangled tangled mess. Are there any other options? Thanks!
I'm attempting to build an angular app that is driven by the CaaS/CMS known as Prismic.io.
Phase one of this project will be a straight forward content-silo (CMS-managed), and phase two will add on more complex web app components. Knowing this, I've decided that Angular would be my best bet, but I'm struggling to think of a good solution to have all of the content lazy-loaded from the Prismic API.
One solution I've decided to explore would be to have a standardized $scope variable, let's call it $scope.loaded. Each controller will do what it must to query my Prismic service for its respective content, and once it's completed, it would set $scope.loaded = true.
The part I'm stuck on with this approach is how exactly to display the page while all of these components are loading. The easiest way would be to include ng-if directives that reference this loaded value, but I feel like there'd be a massive flash of unstyled content. And yes I could use spinners, but the idea of having 90% of the page covered in spinners seems chintzy.
Then I got to wondering: what if I pull up a loading screen for the app until all controllers' $scope.loaded values are truthy? In that case, how would I know which controllers are currently active on the page and reference their respective scopes?
(If you have comments about why this approach is bad, I'd love to hear them as replies rather than answers. I imagine this could create too many http request, for example).
A couple of options here:
Have you looked at ngCloak to see if will help you here with the flicker problem? https://docs.angularjs.org/api/ng/directive/ngCloak.
If you're using jquery, you could have a global spinner that works on concurrent ajax requests http://api.jquery.com/category/ajax/global-ajax-event-handlers/.
Or have a look at something like this global angular spinner https://github.com/monterail/angular-global-spinner/tree/master/src.
If none of these work, you could always create an array on the root scope where each controller/directive registers itself and sets its loading flag. Then add a watch to that variable to see when all components in that array are finished loading.
So I have a bit of a problem.
I'm in a situation where I need to have multiple Backbone.Routers which handle their own routes accordingly etc. and I dynamically load them based on what the main router (Router 1 in the following example) knows about the route currently.
The main problem I am encountering though is something like this.
Router1 loads
Backbone.history.start()
Router1 loads Router2
Router2 dosen't do anything because history has started already
Is there any possible way I can get router2 to look at the current history fragment without potentially calling the routes in router1 again?
IE don't manually call Backbone.history.loadUrl(Backbone.history.getFragment());
Edit:
The main goal is that right now I have two views and well would obviously like a router per view. It makes no sense to have one huge router considering that in the future there may be n views that knows about every single individual view.
I suggest you try to look at MarionetteJS which is a great framework for building composite applications with Backbone. Specifically look at the source code of the MarionetteJS example app. What it does is separate the application into several sub-apps. Each sub-app has its own router, but they all define the separate routers on the parent app. When the parent app initializes, all routers are created, and only then Backbone.history.start() is called. I realize that this answer requires you to dive into Marionette, which has a steep learning curve, but I think it's totally worth it. We've built the entire architecture of the SOOMLA designer web-app on top of it. Marionette has proven to be a great solution when you want to outgrow your repetitive Backbone boilerplate code. Kudos to Derick Bailey for an awesome open source framework.
Could you please provide a jsfiddle which reproduce your case? Because you could normally do that (I personally have an app instantiating a router, starting the history, instantiating several other ones, and it works perfectly fine.)
Until such time, here are some information about routers though:
- when you instantiate a router, the routes are bound to Backbone.history (one unique object)
- this implies that you can't expect both routers to execute a callback
- it also implies that there is a fixed order: the last instantiated router's routes will be checked first
Edit:
Ok, I guess you want both routes executed because you expect someone to get directly into tab1/stuff.
Ugly way: you can stop Backbone.history (Backbone.history.stop()) and start it right afterward, the router2's routes would be bound...
Other possibility: why don't you put all your routes in your main router? Well I guess if you really have too many that's understandable.
Last possibility (that I can think of): use the fact that the last router's routes are tested first, and that's what you need. Change your main router's routes, add a generic one that will catch what you need (for example tab1). Don't do anything, navigate backward to /tab1. Prepare 2 navigates, like this:
this.navigate('/tab1', {trigger: true});
this.once('someEvent', function() {
this.navigate('/tab1/stuff', {trigger: true});
});
If you have generic enough URLs, you can replace tab1 & stuff with arguments you would match with your generic route.
Edit 2:
Ok here's an edit assuming everything I wrote in my last comment and that you access your Backbone views with a hashtag (or an URL) like view/action. I'll try to be the more thorough as I can be (because I still don't have all the details of your problem).
This jsfiddle shows the principle. Now, there's still the fact that it will mess with the client's history (there may be a way to avoid that in Backbone I think, you'd have to look into that if it's a problem for you).
Now, the fact that there may be several other problems. The least of them could be the boilerplate in the secondary routers (you have to put view/ before any route). There are solutions for that, but that would be going too deep. The bigger one is the following:
I've already said it but only one route will be matched. So your main router CANT be used to deal with the fact the the client will change views (say going from view1/action1 to view2/action2, router2 already loaded before). The action2 will be executed, but if you reloaded your views in your main router, that won't be done.
Just as a last comment, you can modify the Routers core initialize method after creating your main router to add boilerplate behavior (reload your view?): here's an example that may suit you.
I know this is a very commonly discussed topic but I can't find anything that answers my question exactly :)
I'm working on a Backbone.js project at the moment. Router wise I don't instantiate views, models or collections within the router but instead just use the router as one way of dealing with state - the router calls methods on my custom controller object.
My controller then instantiates the different views, models and collections for index, show etc. This is all fine and dandy.
I'm just having a bit of a struggle with how to deal with page transitions. I've read all of the great posts on managing zombies etc, and know that whatever happens I have to have some cleanup system for old views (I'm currently using the .close() method that Derick Bailey blogged about).
If I'm going from #show to #index, or any other route change, I understand that it makes sense to just instantiate new, fresh views, models, etc - which is what I see in pretty much every tutorial. Making sure to cleanup old ones, of course.
But, if I'm already on #show say, and I route to another #show page, all of the views etc that I want are already instantiated and rendered. All I want to change is the data of the models and collections.
So I guess my question is why do I not see people re-using views very much. In my head I was thinking if you're already on the page that you want, it would make more sense to just update the url or urlRoot of the model / collection that that view is linked to and re-fetch. This would then trigger a reset event, and all views that need to can subscribe to this and re-render themselves.
But, as I say, I don't see people doing this. Is it just because it's a really bad idea? If someone is doing something like this, how do you deal with tracking 'refreshable' models and collections?
Thanks!
I think it depends a lot on how you are using your views and how complicated/large they are.
If your views are very simple then it is often just easier to rerender the entire view and replace the existing HTML with the new markup (it might also be faster then traversing the DOM to change the necessary parts. However if you have a more complicated view and there is only a small amount of information changing it is most likely better to listen to the appropate attributes change events (eg. _bind('change:name', this.nameChanged,this)) and then only update that part of the DOM.
Keep in mind that while the convention is to use a render method which renders the element, you can just as easily apply an additional refresh event to only refresh certain parts, you can then just swap models (like #jackwanders suggested) and call the refresh method.