Can we use more than one controller in same div - javascript

How can I use two different controllers in the same div element?
How does one access the parent controller model data from inside a child controller?
e.g
<div ng-controller="abc">
<div ng-controller="def"><span>{{name}}</span></div>
</div>
Suppose the model name is in controller abc then how does one access its value?

AngularJS automatically look up from the first $scope to the parent till the $rootScope to find the property matching name.
Thus to answer your question, if the controller def doesn't have a property named name, it is already visible. Otherwise, you should use:
{{$parent.name}}
In your HTML code

The correct way to do this is by having an alias. See Plunker
In your html it would look like
<div ng-controller="Ctrl as Alias">
{{Alias.foo}}
In your javascript it would look like
function Ctrl(){
this.foo = "bar"
}

Related

AngularJS Directive - Multiple directives same name

Let's say I have multiple directives with the same name "parent-elem" (on each page I can have a different number of these directives - dynamic number)
<div ng-app="app">
<div parent-elem></div>
<div parent-elem></div>
<div parent-elem></div>
</div>
Is there a way to know (inside the link function) AngularJS finished render all the directives with the same name on the page?
Inside the directive link function - how do I know this directive is the last rendered?
Note: Not using a ng-repeat
You should have had written, same directive, multiple times :P
Now, that totally depends on your directive, how you make it.
It can keep the counter in a service or rootScope may be whenever it is initialized.
If you are using ng-repeat which you should in this case, you have a bool $last that can tell you if the element rendered is last or not, which you can pass to the directive via any attribute.

Ng-if on directives with two way bindings that override functions

I've set up a directive that will take in a function from the parent controller as one of it's attributes. This function will be replaced by the directives controller and will be accessible by the parent controller by using the passed function. The issue I'm running into is when placing an ng-if attribute on the directive the passed in function is not being replaced anymore. What causes this and how would I go about fixing this issue? I've attached an example
https://jsfiddle.net/dh7jt1zg/1/
<div class="parent" ng-controller="pCtrl">
<h3>Parent - with ng-if</h3>
<div>{{parentHelloWorld()}}</div>
<child ng-if="testBool" rep-fun="parentHelloWorld"></child>
</div>
<br/>
<div class="parent" ng-controller="pCtrl2">
<h3>Parent2 - without ng-if</h3>
<div>{{parentHelloWorld()}}</div>
<child rep-fun="parentHelloWorld"></child>
</div>
Use ng-show instead of ng-if.
ng-if causes element to remove from the DOM.
I think you'd be better off to create a service instead of replacing the function in the child controller. That seems kind of messy to me.
Personally, I'd use a service to register the function and then you can use that same service from the parent controller to call it.

Angular changing parent model from transclude scope

I'm confused from angular transclude scope. I'm trying to make let say collapsible directive. But binding inside the transclude scope will not change model of parent unless I use some object for the model eg. data.
<div>
data.prop: {{data.prop}} <br>
prop: {{prop}}
<collapsible>
data.prop: <input type="text" ng-model="data.prop" /> <br> // WILL CHANGE PARENT
prop: <input type="text" ng-model="prop" /> // WONT CHANGE PARENT
</collapsible>
</div>
I already read this topic and still I don't get it why I must use prefix to the model.
Confused about Angularjs transcluded and isolate scopes & bindings
Working example at http://plnkr.co/edit/z3IvR1a37jdNRCJWG0Yq?p=preview
In my app I'm using object for forms, so it works fine but I just want to know why is that.
When you use an object to bind to the model, your object is passed to the different scope as an reference, not a copy, in Javascript objects are passed to functions as a reference. In that case it will still reference to previous scope.

AngularJS use directive-name in scope as string

I have nested angular.js templates. Each template has it's own directive. Based of the data passed to the ParentTemplate, angular.js should call the matching directive.
<div class="parent-template">
<div class="{{childTemplate}}"></div>
<div class="template1"></div>
</div>
Lets say that $scope.childTemplate = template1. Both divs evaluate to the same content <div class="template1"></div> but only the second div calls the directive to show the template as expected.
I need a dynamic way to call the corresponding template directive
Here is the directive for template1
angular.module('myApp').directive('template1', function(){
return {
restrict: 'C',
templateUrl: 'templates/template1.html'
}
});
Directives for other templates directives work similar.
You try to set the class of the DOM element.
You can do this with ngClass.
Otherwise if you would like to set your directive as an attribute of the DOM element. Like this: <div template1> </div>
You can try this way:
var myEl = angular.element( document.querySelector( '#divID' ) );
myEl.attr('myattr',"attr val");
Try:
<div ng-class="childTemplate"><div>
Did you ever solve this? I have a similar challenge, which I currently solve by using ng-include, like so:
<div class="parent-template">
<div ng-include="'templates/template1'"></div>
<div class="template1"></div>
</div>
This works for your example, but gets more tricky when a directive does more than just wrapping a template, e.g. working with the DOM or adding a controller.
What you can do in that case is using the directive inside the template.
However, this feels all kinda hacky, i'd like a more direct approach
This was, for me, all sparked by an article on react plugins, in which you basically enumerate over a set of react component to get a feature set: https://nylas.com/blog/react-plugins

How to 'destroy' a directive in AngularJS?

I'm using a directive to separate the logic for an entity (for example, a person).
So I have a people service that stores an array of people like:
this.people = ["Person 1", "Person 2", "etc"];
The controller then injects that service, and sends data to a template that contains my directive. So my template looks something like:
<div ng-repeat="person in people">
<person name="person"></person>
</div>
Now, in my directive I have a delete function (called by clicking a button in the directive's template, which looks something like this (People service also injected into directive):
delete People.people[id];
The problem is, the rest of my directive's template remains intact. I want to remove the directive completely upon deletion. How is this possible? I've tried hiding it by using ng-hide and setting a 'deleted' property in the directive's scope to true upon deletion, but the empty (without data) directive template remains. I've looked into scope.$destroy(), element.remove(), etc, but nothing has worked and nothing seems really clear in the documentation...
How can I destroy/remove a directive completely from within itself (i.e. upon calling a delete function)?
Fiddle: http://jsfiddle.net/VSph2/107/
Click delete and the data is gone, but the directive (and template) remains, showing 'name:'. How can I remove the directive completely on delete?
You are deleting object, but empty element in array remains, it is just null reference instead of pointing to an existing object.
Use
this.peopleIds.splice(this.peopleIds.indexOf(personId), 1);
to remove it from array, and that element will not be rendered in for loop anymore.
Reference: How do I remove a particular element from an array in JavaScript?

Categories