I'm pretty new to backbone.js and am still learning how everything works. I'm trying to understand how the initialize option of the backbone router works, and haven't been able to find any good documentation or examples, so I was hoping someone here could help me understand it. I actually have a couple of questions about it...
If I define a router with multiple routes, is the initialize function called each time one of those routes is called with a call to router.navigate??
What would be the most appropriate way to delay the execution of a route handler until after initialization has occurred?
Thanks.
If I define a router with multiple routes, is the initialize function
called each time one of those routes is called with a call to
router.navigate??
Think of initialize function as constructor function you would normally find in other OOP languages or OOP concepts. Whenever you create a new instance, the initialize function is called. Hence you can put up any initialization code, settings or defaults, etc in that.
What would be the most appropriate way to delay the execution of a
route handler until after initialization has occurred?
You don't need to worry about it, backbone will fire the event at the appropriate time.
Just keep in mind that initialize is called only when you create a new instance of the class. using new keyword.
Related
How can I pass asynchronous data from a parent controller to a child component? I am using angular 1.5.0 in order to create a child component that I would like to reuse in other views/controllers. I want to make the server calls in a parent controller/component and use the returned data in the child component, maybe modify it using a function. If I want my component to be truly reusable, then I don't want to have to put any code into my parent controller to direct the data.
In theory, I should be able to instantiate the component in the parent controller view, pass in the asynchronous data, and be able to use it in a function in the component when the data is returned.
I encountered this exact same problem with Angular 2. Am I not supposed to pass asynchronous data to components? If I want to do something with asynchronous data, do I always have to call for it in the component? This seems to be a huge flaw if someone needs to view the data in multiple ways and wants to use it in multiple components... This has been bugging me for days, and years if you count the Angular 2 issues. Any explanation or reasoning would be appreciated. Thank you in advance.
Here is an article which instructs to embed a component within a component so that you can start watching a binding. It is a very round about way of doing things, but it seems to do the job. It just seems ludicrous this functionality was not already anticipated when they created components, most data used in general is asynchronous, and it would be nice to have components that only deal with taking in the data, massaging it, and displaying it; without having to make it's own service calls. What if you have a few components that display the same data and you wish to embed them all in a controller's view that does the work of getting and updating the data and then passing it to those components? This seems like a likely scenario, and one I often encounter. So here is the article:
https://www.bersling.com/2016/09/10/wait-for-the-bindings-of-a-directive-in-angular/
It functions even though the code is not as pretty as wished, and I don't know the repercussions of this particular implementation, but it works. If I am overlooking an unforeseen issue, or if there is a better way, I am open to suggestions. Thank you.
I have a project I'm developing which includes articles that can be commented on (comments stored in separate table of course). I want to perform pre logic on a field from each comment, wherever they are loaded through-out the app. The data logic I want to performed is from a custom written component.
The logical place to me that this could be achieved globally is from the comment model, but I could be wrong.
I'm not even 100% if I can use a component from a model, but I've been trying to do this logic using the afterFind() call-back function:
function afterFind($results) {
foreach ($results as $key => $val) {
if (isset($val['Comment']['created'])) {
$results[$key]['Comment']['created'] = $this->Dateconvert->howLongAgo($val['Comment']['created']);;
}
}
return $results;
}
I have tried echoing from inside this function and it doesn't actually seem to be getting called but searching hasn't revealed any functions that do, but I believe afterFind() is best to illustrate what I'm trying to achieve.
So I am looking for a solution where I can performed the post-load logic on articles comments, whether they are being loaded from other controllers with associations to comments or in the comments controller. Basically a global one hit solution :D
cakephp indicates that components are for controllers and behaviours for models and helpers for view...
knowing that first, you may also know that you can use any part of it wherever you want because cake still php, though is not recomended... if is a library of functions you may want to put it inside the libs folders and access it from there.
how, easy use App::import('component', 'nameComponent'); component can be lib, controller, etc..
Having said that, afterFind is a good place to do after load things, remember that this function is call ONLY when a find is used, if you use, any other like query or save or update it won't be called.
hope this helps you :)
I'm trying to wrap my head around backbone.js but I'm finding it hard due to the lack of (IMO) good examples.
First of all, what is the best way of getting a link to an object.
If I want to get the edit url of an Album model I could do album.url() + '/edit', is this really the best way?
Also, I'm trying to make my application work 100% without javascript so I don't want my URLs/links to say /albums/#1/edit, I want it to be /albums/1/edit and override this in JS.
I'm thinking I create normal URLs and use jQuery.live to call router.navigate in backbone.js
I never got this to work however, when I call router.navigate('/albums/2', true) the URL changes but my show action is never called. If I refresh it's called so the route is matched.
What am I missing?
The basic answer, which is kind of frustrating, is "there is no preferred way!". Backbone.js doesn't tell you how to set up links, you can do it any way you like. I found this flexibility just as annoying as you do, at least at first.
So here's the way I'm approaching this on my current project, with the (big) caveat that this is just one of many ways to do things in Backbone:
For the most part, I don't use actual links. There's no explicit reason not to, but it means you have to keep track of a bunch of URL strings that have to be consistent. I would rather stick all the URL formatting in my routers and not deal with it elsewhere.
To open a new "top-level" view, like an editing screen, I set something that fires an event. In the application I'm currently working on, I have a global State model, and to open a new view I call state.set({ topview: MyTopView }). This causes the state object to trigger change:topview.
Any piece of the UI that needs to change when the top-level view changes has an update method bound to change:topview. When the event fires, they look at state.get('topview') and update as necessary.
I treat my routers as only marginally specialized parts of the UI - they're essentially views that render in the browser address bar, rather than the window. Like other views, they update the state object on UI events (i.e. a new URL), and like other views, they listen to the state object for changes that cause them to update. The logic that the editing screen has the URL albums/<albumid>/edit is fully encapsulated in the router, and I don't refer to it anywhere else.
This works well for me, but it adds an entirely new pattern, the global State object, to the Backbone structure, so I can hardly call this the "preferred" approach.
Update: Also note that .url(), in the Backbone idiom, refers to the model's URL in the back-end API, not the front-end URL (it's not like Django's get_absolute_url). There is no method in the default Backbone setup that gives you a user-facing URL for your model - you'd have to write this yourself.
Also, I'm trying to make my application work 100% without javascript; so I don't want my URLs/links to say /albums/#1/edit, I want it to be /albums/1/edit and override this in JS.
you can do exactly this w/ pushState. just enable it in your Backbone.history.start call:
Backbone.history.start({pushState: true})
this tells Backbone to use the HTML5 History API (a.k.a. "PushState"), which uses full URLs exactly like you're wanting.
read up on the history api here: http://diveintohtml5.ep.io/history.html
and I wrote up a 2 part series on using pushstate w/ the second part focusing on progressive enhancement in backbone, to do what you're needing:
http://lostechies.com/derickbailey/2011/09/26/seo-and-accessibility-with-html5-pushstate-part-1-introducing-pushstate/
and
http://lostechies.com/derickbailey/2011/09/26/seo-and-accessibility-with-html5-pushstate-part-2-progressive-enhancement-with-backbone-js/
hope that helps :)
I have a small calendar widget-type thing on many pages throughout my site. The goal is for it to retrieve events from X category that fall between Y and Z dates.
My assumption (I'm new to CakePHP) was that I should create a component, and have it do the query. Something like this:
class CalendarComponent extends Object {
var $uses = array('Event');
function getEvents($category = null, $date = null, $limit = null) {
$events = $this->Event->find('list', //conditions to get correct events
return $events;
}
}
BUT, according to this CakeBook page:
To access/use a model in a component
is not generally recommended
So - where would I store this logic / model call if not in a component? I've admittedly not used a component yet (or not created one anyway) due to lack of really understanding how I should use them - any snippet of advice on this is also VERY welcome.
Great question in my opinion and I imagine one that comes up quite often. I was actually dealing with a similar problem where I wanted some site-wide data gathering or functionality shoved into a component.
The first thing to keep in mind:
The book is a guideline.
These 'rules' aren't rules. If there's a good reason for breaking the rule and you understand why the rule is being broken then break the damn thing! Cake itself breaks this rule quite often.
Core components that require/use models:
Acl
Auth
Sessions (fairly positive you can save session data to a model)
So, clearly there are use cases where you need to use a model inside a component. How do you do it though?
Well, there's a couple different ways. What I wound up going with? Something like this:
<?php
ModelLoadingComponent extends Object {
public function startup($controller) {
$controller->loadModel('Model');
$this->Model = $controller->Model;
}
}
?>
That's it! Your component is now setup to use $this->Model...just like you would in a controller.
Edit:
Sorry, to clarify: no, you don't have to setup a new component to load models. I was showing an example for how you could load a component in any model. The startup function I used is a component-specific callback, there's a whole slew of them http://book.cakephp.org/view/998/MVC-Class-Access-Within-Components. These callback methods make components a lot easier to work with. I highly recommend looking at this part of the components tutorial if nothing else.
If you were working inside an AppController object you could call $this->loadModel() but we aren't working an AppController! We're working with a component, really an Object. There is no Object::loadModel() so we have to come up with a different way to get that model. This is where $controller comes into play in our startup callback.
When the startup method is invoked by Cake it will pass the $controller object it's working with on this dispatch as the first parameter. With this we're able to access controller methods...like loadModel().
Why do we do it this way?
Well, we could use ClassRegistry::init('Model') in each of our component methods that need to use the model. If you have 10 methods in your component and only 1 of them uses the model this might work. However, what if you have 10 methods in your component and all 10 of them use the model? Well, you'd be calling ClassRegistry::init('Model') 10 times! That's a lot of overhead when what you really want is just 1 model object. With this method the component is creating one model object. The one we create in startup.
I hope this clarifies your questions and provides some insight into why I use this method for models in components.
Edit: Added a code clarification after I did some experimenting.
I think writing a component is overkill in this case and it would be cleaner to put the getEvents method into the Event model.
i need some help
which is when i on my index.ctp/view.ctp, i need to call to my controller function to perform some task. what code i can use to perform this action?
i need to call to my controller function, which send in a value (user_id) to the function and get me a certain action. how can i do that? i might calling in a javascript function as well.
If you need to call a Controller function from the View, you're doing it wrong. It's not proper MVC.
Having said that, requestAction would be the proper, albeit slowest way to do so. You could hack around a bit more and get an instance of the Controller from the ClassRegistry. But I'd seriously recommend you to restructure your program flow so you don't need to do this to begin with.
You should probably perform the task in the controller before you get the view. But if you need to do some view work on the data you are displaying you might want to consider making a Helper class.
http://book.cakephp.org/view/101/Creating-Helpers
If your task doesn't generate any output - you might want to consider doing it in the controller before you even get to the view stage.
If your task has some form of output - use requestAction with a view Element
http://bakery.cakephp.org/articles/view/creating-reusable-elements-with-requestaction
That link should be a good starting point. There are also good posts by Mark Story on his blog that detail the actual performance of requestAction and it really isn't that bad if you don't abuse it all over the place.
http://mark-story.com/posts/view/how-using-requestaction-increased-performance-on-my-site
http://mark-story.com/nodes/view/reducing-requestaction-use-in-your-cakephp-sites-with-fat-models
If you really need to trigger some sort of logic in a predictable way and that logic might happen in more than one place you can also use an event observer pattern to trigger the controller action you need to run.
http://cakealot.com/2009/04/eventful-a-cakephp-event-system/