AngularJS - Similar view - Should i use same view with multiple controllers? - javascript

Let's say we are implementing CRUD operations for a specific object - those view would be very similiar and i think i should use the same view with multiple controllers. Is there a way to choose the controller dinamicaly based on a parameter or this type of action can be only taken inside the controller?

You technically can, but according to the exellent angular styleguide from Johnpapa, style Y037 :
Define a controller for a view, and try not to reuse the controller
for other views.
Though, you're actually right thinking that some CRUD logic should be made common and abstracted. Controllers are just not the right place; Factories (ie services) are.

You can use the same view on different controllers but it depends on what you are doing inside the view and whether or not the controller has the necessary members within the $scope object that are bound in the view. You can add an "action" variable on your $scope object and modify the view based on the same.

Related

Angular view change resets $scope variables

Say I have two views that share a controller. Both views use the ng-route service. If a scope variable is changed in one view and then you switch to the second view, how come the second view doesn't update?
Example: My controller has a variable that = "hello". I output this variable just fine in both views. In view one I have an onclick that updates the variable to say "Whatsup". That works fine, but after the event I switch views and the second view is outputting "hello" still. Is there a way to share these? If not, then what is a technique to share data?
I'd like you to know that AngularJS is designed for SINGLE PAGE APPLICATIONS (SPA) so this behavior is not supported by the framework.
Each view have a different scope even though they share the same controller. So updating a scope variable for one view won't update the other.
If you want this behavior, I suggest using $on to listen to events.
Also, on your code you have $scope.test = 'hi'; that is hard-coded on your controller with no conditions or whatsoever which is why it reflects on both of your views who share the same controller.
Best practice is to have one view per controller. As your site scales, it would get very hard to manage multiple templates/views with one controller.
A service is the way to share data between controllers.
For your example, you could have a activate functions that are called when each view is rendered that gets the updated variable from the service you inject. Your on lick function should save the variable to the service to make it available across controllers.

Angularjs Can I change $scope value of a controller from another controller?

I have an HTML div , like
<div id="loader-container" data-ng-controller="LoaderController" ng-show="shouldShow">
Some html design
</div>
And in my controller
angular.module('core').controller('LoaderController', ['$scope','$location', 'Authentication', '$rootScope',
function($scope,$location, Authentication, $rootScope) {
$scope.shouldShow = true;
}
]);
And now, I want to hide that html div from another controller, That's why I tried to make $scope.shouldShow variable as false from another controller. So how can I make
$scope.shouldShow = false;
from another controller. Is it possible or any alternative way.?
every controller will create a new Scope.
Hence the changing the scope in one controller will not reflect in the scope of other controller.
If you want to share a property across the controllers create that variable on the $rootScope and use it.
In Controller
$scope.$root.shouldShow = true; //or false
In Markup
<div ng-show="$root.shouldShow"></div>
It's not a good idea to manipulate a $scope of a controller from a different controller directly. It would make your controllers very tightly coupled.
One commonly accepted way to communicate between controllers is through messages using the publish-subscribe pattern.
If your controllers are in completely separate components and you just need to notify the other controller, you can use the $broadcast/$emit and $on methods of the scope object to broadcast a message from one controller and listening to a specific message in a different controller. When an action happens that should change the shouldShow variable, you can just broadcast a message and make the other controller listen and act on it.
Root Scope API
Another common way to communicate between controllers is by using angular services, acting as a mediator between controllers.
If your controllers are part of the same component/module, and you need to share state/behavior between those, then using an angular service to encapsulate that logic and expose it would be an OK approach (services are singletons in Angular). That would be pretty simple to implement.
However, not knowing more details about your exact requirements, it's hard to design a proper solution.
Thanks to #Callum Linington for discussing the alternatives in the comments.

AngularJS: Passing data from a transclude directive to the isolated scope of a sub-directive

Based on this Plunker: http://plnkr.co/edit/GufJjrn3OxYVSf2oLD5n?p=preview
I have two directives, for the sake of simplicity, let's name them directiveBlue and directiveRed.
directiveRed has to be a sub element of directiveBlue.
The MainCtrl of our mini app has a simple array under the variable $scope.elements.
This variable is passed to the isolate scope that directiveBlue creates via the data-elements attribute. Notice that the directiveBlue has to be a transclude directive.
Then my main problem is, how do I pass the array of elements to the directiveRed without having to get it doing it via $scope.$parent.elements which seems to me, is a bad practice and then it makes the code tightly coupled.
Any changes to the elements in the deepest directive should then be synched with the rest of the scopes.
Is there any good practice or valid solution for this?
Thanks!
EDIT:
To be more concrete on my use case:
I've created a plunker (http://plnkr.co/edit/i2Busz6E8ehlkG3uEllh?p=preview) with a more concrete situation, where I want to have directive for an action group, I've implemented an option as a simple directive and I want to place my logic in the directives controllers. The method selectAll is pretty simple, but I can imagine having more complex actions which would require the elements from the top scope.
there are plenty of solutions, but without knowing what your goal is, it is more or less guessing.
The following quote is from the angular docs for $compile and describes the use of controller
(...)The controller is instantiated before the pre-linking phase and it is shared with other directives (see require attribute). This allows the directives to communicate with each other and augment each other's behavior. The controller is injectable(...)
a fork of your plnkr to show how to access MainCtrl's $scope.elements in directiveBlue and directiveRed

AngularJS: What is the best practice to make communication between components?

I have a problem reasoning about components communication.
The main question I tried to reason about and failed: what should I use - $watch or $on ($broadcast/$emit) to establish the communication between components?
I see three basic cases:
Controller + Directive. They communicate naturally using the $scope bidibinding. I just put the service, which incapsulates some shared state, in the $scope using some object ($scope.filter = {}).
This approach seems very reasonable to me.
Controller + Controller. I use the DI to inject singleton services with incapsulated state to communicate between controllers. Those services are bounded to directives using the previous approach. This gives me the data binding out-of-the-box.
Directive + Directive. This is the blind spot in my reasoning. I have directives, that reside in different scopes, in the same scope, etc.
I have directives that must reflect all changes (think about slider + charts) and directives, that must trigger the http request (think about select input).
So, the questions are:
What should I use - $watch or $on ($broadcast/$emit) to establish the communication between components?
Should I tend to use $watch in directive-to-directive communication?
Or should I tend to use $broadcast in directive-to-directive case?
Is it better to share the state using injection+binding or injection+events?
I think this depends on the use case for your directives/components. If you expect to be able to re-use a component without having to modify the scope that the component lives in then using broadcast/emit/on would make more sense. IMO if a component internally has some information that I want to be able to retrieve and do different things with, then the broadcast/emit/on scheme makes the most sense.
If on the other hand I need to trigger some service calls in response to something in a directive or I want to share state between a couple of views I end up using a service.
As noted in the comments another alternative that exists is using the require property in the directive definition object:
require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent']
require - Require another directive and inject its controller as the
fourth argument to the linking function. The require takes a string
name (or array of strings) of the directive(s) to pass in. If an array
is used, the injected argument will be an array in corresponding
order. If no such directive can be found or if the directive does not
have a controller, then an error is raised. The name can be prefixed
with:
(no prefix) - Locate the required controller on the current element.
? - Attempt to locate the required controller, or return null if not found.
^ - Locate the required controller by searching the element's parents.
?^ - Attempt to locate the required controller by searching the element's parents, or return null if not found.
This can be useful in cases where you're creating a "compound component" where multiple directives make more sense than trying to encapsulate all of the functionality into one directive, but you still require some communication between the "main/wrapping directive" and it's siblings/children.
I know this isn't a clear cut answer but I'm not sure that there is one. Open to edits/comments to modify if I'm missing some points.

Is AngularJS really MVC?

I'm looking through examples on the AngularJS home page — specifically “Add Some Control”. I don’t quite understand how it maps to MVC pattern.
It’s more or less clear that the template (index.html) can be thought of as the view, objects constructed by TodoCtrl from todo.js as the controller, but where is a model? Attributes like ng-model map to some internal pieces of the framework and don’t directly expose an object which we could call a model.
Is it correct to call AngularJS an MVC framework?
The core idea behind MVC is that you have clear separation in your code between
managing its data (model), the application logic (controller), and presenting the data
to the user (view).
The view gets data from the model to display to the user. When a user interacts with the
application by clicking or typing, the controller responds by changing data in the model.
Finally, the model notifies the view that a change has occurred so that it can update what
it displays.
In Angular applications, the view is the Document Object Model (DOM), the controllers
are JavaScript classes, and the model data is stored in object properties.
I havent read up on Angular. However, keep in mind that "true" MVC means that the Model contains business Logic, the Controller takes care of communicating user input to the Model, and the View gets its own data from the Model. Many so called MVC frameworks are actually not implementing MVC the right way: They are overloading the Controller With to much responsibility, as in making the Controller responsible also to update the View. That is not what the Controller was intended to do, and in such cases you get what is called a "fat Controller". There is a misconseption among many webdevelopers that the View is simply a "template". This is both true and false; It is a template but it get its own data directly from the Model - not via the Controller.
But as I started out saying: I havent yet read up on Angular, but you might have so yourself and you should be able to find out if Angular is truly a MVC framework by looking at what the different Components in the Framework does.
The attributes map into the scope variable as defined in the controller. For example, if you have some JS objects which represent your business logic, you can put those in the scope variable, and then the attributes can be mapped into the model itself instead of some arbitrary values in the scope variable.
If anything that can store data in a object is considered a model than every front end framework (view) could be considered to have a model. They can all store data in objects and present them in the view. I think calling angular a mvc is really a marketing ploy, trying to make angular seem like it is more than it is.
See:
https://www.pluralsight.com/blog/software-development/tutorial-angularjs-mvc-implementation
In the controller, is where they give their example of angular's as a model. If it can't assist in the storage of persistent data it isn't much of a model.

Categories

Resources