Share data between controllers AngularJS - angularjs

In our case, we have a search function in our application which shows the search results after entering a search term. The search results are products in our case. When we click on one of these products we are send to the page with information regarding this product. Now our problem, when we want to go back to the search page we want a method to return to the exact same page as before we left the search page. And not an entirely new search page.
We have divided our HTML in 3 views, which we load with the UIRouter.
We need to share data between the header, content and footer. When we show our search results, we want to show the amount of results in the header for example.
In short; we need to share our data between controllers / views. What will be the best solution?
We have thought about:
Adding a mainController to the body and using this as a medium to communicate data between controllers..
Store all data in a factory and access this factory direct from all controllers. But will all views be updated directly on data change? (2 way binding?)
However, we didn't get it working yet. What would be the best way to manage this?

As mertins mentioned in his comment, a service would do fine for this purpose.
Inject that service to all relevant controllers and indeed, thanks to 2-way binding all relevant data will be updated properly.
Don't use a controller, that's not what they are meant for!
If you need a code example for the service injection comment and I'll update this answer.

Related

AngularJS - Shop list best practice

I'm new to AngularJS, and i'm want to know what's the best and easiest practices to do this simple shop list application.
So this is my shop:
I got three servers in my select input. Each server got own list of items, displayed in another component.
I'm thinking about creating routes with variables like localhost:4200/shop/{server1} which gonna show my list of items based on url path. Select option will just change path in my application to show shop list for specific server.
Is it a good practice, or there is better and easier solution to implement this simple shop application?
If you're asking if filtering data with routing is a good practice with Angular, I can say that it is not a bad one. Here's a link to the official Angular documentation about routing : Angular - Routing
But if you're asking if it is the only way to filter data or spread parameters, the answer is clearly no. Angular projects are SPA (Single Page Application), so you can do everything without touching the url.
For a quick example, you can attach a (click) event on your elements that display the shop list you want
I think you can use just one component and three different click events to display three different results. One component can work in your case. Using a router and routing logic for your requirement will be a costly affair. Your user will have a better application feel if these are covered in just one component and with three different click events.

General approach of left side menu that loads different content in a center of the page

I've started to learn AngularJS but I need some application design hints. Of course I'm not asking about the layout but ... how to design my application and it's controllers in a proper way. I have left sidebar with a menu that is loaded from the web using JSON. That needs a controller. That's fine. It works for me. There's a content box as well in a center of my page that loads some data dynamically. In my opinion it requires another controller.
And now comes my solution, that somehow doesn't look good IMHO. When I click a menu item in my sidebar I'm loading a content. Then I'm passing this data into a Service which emits an Event afterwards to the Second controller (which is responsible for controlling my content in a center of my page). When it receives this event it simply gets previously loaded data from the Service and displays it. It generally works.... but ... I'm pretty sure that's not the proper way of doing this.
I would be grateful for any hints. AngularJS has a really poor documentation and tutorial :(
cheers
EDIT:
OK. That's my basic application using JQuery:
http://greatanubis-motoscore.rhcloud.com/index
And that's the same application I'm converting into AngularJS:
http://greatanubis-motoscore.rhcloud.com/angular/index
No worries, some text is in Polish but... I think it really doesn't matter ;)
Note for the AngularJS version: At the moment the content is a HTML but finally it will load JSON data as the other controllers.
I would go about doing this with angular ui-router. With ui-router you can achieve this in a couple of ways. You can use nested routing to have a base state (Your sidebar menu, header etc.) which will act as your shell page, this can have its own controller as well. You could then define each of those other views as child states of the base state. These child states can also have their own controller/views as well, but they will be sitting inside the base state (both visually, and also inherit $scope properties of the base state) optionally they can have separated URLs themselves, but they don't have to, you can just change states without changing the url, by leaving the URL bit empty when you define different states in your $stateProvider configs. Another way would be to use the multiple named views feature.

Angular ui-router nested views don't refresh data retrieved by Angular Services

I have a nontrivial Angular SPA that uses ui-router to manage multiple views, many of which are visible at the same time. I need models to be visible across controllers, so I have services written that allow me to have controllers pull down fresh copies of model data that has been updated.
I apologize in advance for the length of the question, but I will state the problem then state what I have done to address issues I'm sure others in the Angular community have struggled with.
I believe my problem is not understanding the lifecycle of controllers / views, because I get behavior where a controller initializes correctly the first time I go there, but then seems to never run again, even when I navigate to it using something like $state.go("state name").
In one view (contrived example), I show a summary of information about a customer, and in another view I allow a user to update that customer's more detailed profile. I want a user to edit, say, the customer last name in the detailed view, and have the summary view automatically recognize the change and display it.
I have a fiddle that shows 3 views and a simple password changing Service. The flow goes like this:
You can see each view gets initialized and displays the initial password retrieved from the service. All views are in sync with the DataService.
The middle view allows you to enter a new password and change the one stored in the service. Console logging confirms that the service picks up the new password just like you would expect.
(odd behavior #1) When the DataService receives the new password, I would expect the other 2 views (top and bottom) to display the new one. They don't... they still display the initial password.
There is a button to allow a user to go to another state via $state.go("state name") (a child state of the original) which also retrieves the password and displays it. This works the first time (see #5). Now the top view shows the outdated password, the middle view shows the new one, and the bottom one shows the new one as well. This seems normal, since the new view is invoked after the DataService contains a new password value.
(odd behavior #2) If I click back in the middle view and change the password again, and click the button to change states again, the bottom view (which updated just fine in step #4) no longer updates its copy of the password. Now all 3 views show different passwords, even though I am using a single service to pass values between controllers as suggested pretty much everywhere you look for Angular best practices.
Some possible solutions:
Tim Kindberg has an excellent slideshow here that seems to recommend using ui-router's state heirarchy to "pass" data among views that need to pick up values from other views. For a smaller-scale app I think I would settle on this, but I expect our application to have 30+ views displaying data from over 100 REST endpoints. I don't feel comfortable maintaining an application where all the data is being shared by a complex inheiritance tree. Especially using a routing framework that is at version 0.2.8.
I can use events to have controllers listen for changes in the data model. This actually works well. To accommodate performance concerns, I am using $rootScope.emit() and a $scope.$onRootScope('event name') decorator I found on here. With this approach I am less concerned about event performance than I am about wiring this huge app with a bunch of event listeners tying everything together. There is a question about the wisdom of wiring a large app using angular events here.
Using $watch on the value in the DataService? I have not tried this but I am hesitant to hinge an app this size on hundreds of $watches for performances reasons.
A third-party library like bacon.js (or any of a dozen others) that may simplify the event spaghetti, or create observable models that my controllers can watch without the risk of $digestageddon. Of course, if there is a concise way to handle my issue using Angular, I'd prefer not to muddy the app with 3rd party dependencies.
Something that lets controllers actually reference .service modules by reference, so I don't have to depend on tons of event wiring, complex state hierarchies, 3rd party libraries, or seeding the app with hundreds of $watches and then kicking off $digests to update controllers' references to Angular services?
Some solution that relies on time-tested OO and design patterns and not a 3rd-party library or framework that has a version that starts with 0.*.
Thanks in advance... I appreciate the help!
This is no problem of ui.router. If you intend for your model (your data service) to be a single source of truth, you have to refrain from destroying it.. err.. the reference to it that is. And in your case, assigning a primitve (a string) directly to the scope, instead of a reference to it. In other words...
var password = {pw:'initial value'};
and then later setting/binding only on
password.pw = newpassword
{{password.pw}}
Heres a fiddle. And also here is a short little read on scopes, It also includes a video of an angular meetup where Misko talks about "always have(ing) a dot in your model" link and how the $scope is a place to expose your model, not be your model. (aka not a place to assign primitives like password = 'initial value')
Hope this helps!
try remove the animation property of your ion nav view.
remove the property
animation="slide-left-right"
it would be ok.

Search results filter - controller or service or filter?

I have a search results page. The search results page is basically one large controller at the moment. I have code which is for the filters however this isn't an angularjs filter as such because I'm making another search to back-end and I'm not just returning a different array set. I want to keep the filter separete from the search results controller because its already large as it is. My question is: do I make it another controller and broadcast changes to the searchResults controller or do I make it a service or is it actually a filter?
I'm currently thinking a separete controller makes more sense as I'm still having to use scope but with a service I can only use $rootScope it seems.
Overall it would be good to know what calls for a filter and controller.
It all depends on where you want to do the data filtering. If you're doing it server-side, then I'd put it in the service that you're probably already using to get the data. If you're not using a service to get the data, I'd recommend pulling that out of the controller first.
If you want to just grab all the data and then handle the filtering in the client, then you can create a filter module and pass it into the app to be called in the view. Depending on how complex your filtering is, it might be as simple as using one of Angular's built-in filters.
Hard to get more specific without knowing more about what you're trying to accomplish.

Can cakephp have multiple 'content'?

So in cakephp's layout we have the
$this->fetch('content')
right? does it mean i can only have one 'content' in one layout? I really need multiple content from multiple controller can it be done? how? please help me!!!
The layout isn't capable of pulling information from the controller. The controller is the place where the view is prepared to be placed within the layout.
When you access a CakePHP URL, it's in the following format:
http://example.com/controller/action
In other words, you're connecting directly to the controller, not the layout.
You use the controller to get data from the Models and then when everything is ready you set it to a view and then the view is displayed, with the layout wrapped around it. So, you only put HTML/CSS etc in your layout if you want it to appear in all of your views.
To answer your question, though, your controllers don't actually have any content. Your content is (presumably) in your database. Databases are accessed using Models and it's possible to pull data from multiple Models using a single controller, which is usually done by defining relationships between multiple Models.

Resources