Data binding not working in nested directive - angularjs

I am new to angular world.I am trying to create an app with reusable nested directives.
Here is a link to my code.
http://plnkr.co/edit/T2CNKQkLEoxjb3TGdp67?p=preview
I have created two containers and bound them to two set of data.Now if I click the buttons it should show me the data bound to parent scope.But it's showing only one set of data.When i debug it seems that both the buttons are bound to one single scope.How do it separate the scope of this two buttons.

I got it working with some help.
I needed to use ng-click instead of onclick()
If anyone is facing the same problem here is the updated code.Working Code
Thanks

Since there is so much commented code in the plunkr, it is a bit confusing at what you are asking. However one big problem is the line:
<container data="{{pie2}}"></container>
The curly braces {{ tell Angular to write out your variable as a string, so you lose any reference to the variable itself. Instead you would want:
<container data="pie2"></container>
And the scope of the directive would become:
scope :{
data:"="
},
That will help you get the reference you are expecting. Let me know if this gets you on the right path. Or if you can simplify/clarify your quesiton further.

Related

Nested Controllers in Angularjs/Bootstrap Image Carousel Issue

I am new to Angular development. I have a list of images which is being retrieved from a remote server and needs to be displayed in two different image carousels. At the moment, I have a setup like:
<div ng-controller="MainCtrl">
<div ng-controller="CarouselCtrl"></div>
<div ng-controller="CarouselCtrl"></div>
</div>
Where the data is retrieved and stored in the scope of MainCtrl, then used in both image carousels. But that ends up with the two carousels linked together, so that any operations on one are reflected on the other.
Plunker example here:
http://plnkr.co/edit/e79x0d2fF5zwx0UwXIxW?p=preview
What is the best and right way to fix this, so that the same underlying data set can be used by both carousels, but their interactions are not tied together?
Edited: I forgot that about the loose way that parameters can be set/defined. Both carousels were using the same parameter (.active) to determine their active slide. So when one changed .active, the other reflected the change. Changing them to .activeA and .activeB de-linked in in the way I needed them delinked.
The reason is that both Carousels are being bound to the same $scope.kittens property, this is two way data binding, changing the index of one, will change the other, the solution is Either to create a Directive with an Isolated scope that will create a carousel that has it is own separate scope, Or if you want to keep it simple, construct another Scope property (kittens2) that is a copy of the first property :
$scope.kittens2 = angular.copy($scope.kittens);
this will create a new scope property that is not data bound with the first one, then, in your second carousel change the ng repeat to iterate to the new scope property that has its own scope now.
<slide ng-repeat="kitten in kittens2" active="kitten.active">
this way you are separating the scopes, this solution is just to keep the example simple, but the right way is to use directives with Isolated scopes.
Note that doing :
$scope.kittens2 = $scope.kittens
will not work because you are binding the kittens2 property again with the kittens property, angular.copy copies the old object to a new object with a different reference.

Understanding ng-show in AngularJS directives

Given the following code:
http://jsbin.com/uYETOSUM/2/edit?html,js,output
I want to only show the first dropdown first (parent question in JSON). After user have selected an option I want to show one of the two other dropdowns (children in additionalQuestion object in JSON). Which dropdown to show is given in the JSON used to create the form input fields.
To do this I've experimented with ng-show, but I don't seem to find the proper place to put the custom ng-show code. I want ng-show to be like this in the template:
ng-show"showQuestion()"
where showQuestion() iterates through all questions and matches the PreviousQuestionConstraint to see which of the other questions to show based on the value of the selected option in the first question.
Should it be in the Controller?
Should it be in the Directive?
Should it be in the linker function in the Directive?
All attempts so far have resulted in nothing being shown.
After much hassle I've managed to get a working example for you using the &attr isolated scope syntax which provides a way to execute an expression in the context of the parent scope, in your example all the way up to the showQuestion() function on your QuestionsCtrl controller.
http://jsbin.com/EkIqAju/2/edit

Angular directive failing silently (directive rendered too soon?)

I have an Angular app with a custom element directive (<uber-table>). <uber-table> is supposed to take a collection of objects, render them into a <table> and add some functionality (click row to toggle the underlying object as selected, search box for live filtering, action links on each row with customized click callback(s) for each object). I created a Plunker with the relevant code. Please note that Plunker is giving an error about map (Object [object Object] has no method 'map'), but locally I am not getting any errors.
The post-link function's element parameter is not the <uber-table> element as I expected. Instead it is the template's <div class="uber-table"> element. This is preventing me from extracting data from <uber-table>. What am I doing wrong? Any help will be much appreciated.
Here's a rundown on some of the issues.
First main issue is you want existing content already within the uber-table markup to exist, as well as a new template. Unless told otherwise the existing content ( columns) in this case will be overwritten. In order to include existing content in a directive that has a template, you need to set transclude:true then identify within template where this existing content needs to be placed using ng-transclude on element that will be parent of the content.
Here's demo with transclude fixed
New problems arise now where you are trying to use jQuery to loop over columns and return angular attrs => column.attrs . This throws undefined error.
I haven't tried to unravel this enough to sort out the columns issues yet. They should likely be handled by directive of their own
UPDATE: here's slightly revised error free version using jQuery to parse column count. I'm afraid am still confused a bit by structure of this. I don't see need to use jQuery to parse colunms, this could be converted to directive or pass column definitions into main directive from controller scope
After trying several things and looking at the documentation again, I finally got it working. The solution was to put the post-link function inside the compile function. Also I had to update my isolated scope to use =, set replace to true and set transclude to 'element'.
I updated Plunker if anybody wants to see the changes. The Plunker version isn't working, but since it is working locally, I'm not going to spend too much time on it.

Dynamically creating an ng-switch inside a directive

I'm trying to create a new directive that selects among several children using an ng-switch. This example is not much more than creating an ng-switch inside a directive, but eventually the directive will have more display sugar and some automatic functions so it seemed that creating a directive was the right solution.
My progress so far is in this plunker:
http://plnkr.co/edit/yeCiIOCQswYJHyTozQUZ
The $compile I'm doing seems to be evaluating the switch, and determining that the value doesn't match any of the when clauses which shouldn't be true. You can see that by inspecting the elements in the rendered picker.
I'm also concerned that calling $compile at this stage seems to have thrown away the item list, so it seems like I'm barking up the wrong tree.
How do I get the transcluded content to re-evaluate within the current state?
Update
I think I was barking up the wrong tree. Mathew's answer got me started in the right direction, so it was a big help.
As far as I can tell trying to construct a directive (ng-switch) inside a directive is a bad idea. In the previous plunker when the compile happened the template was changed permanently. That means if I changed the which parameter it wouldn't update. That's what was smelling funny to me in the first place.
Here is a revised plunker:
http://plnkr.co/edit/WUVgdXjwedxO4356321s
In this case, there's a watch on the 'which' value that refires the transclusion. That function removes the previous entry (if any) and adds the new one. There's a couple added benefits.
First I removed the 'item' directive. There's no reason for it to exist, since I'm just looking at the class. Second, I used $animator to do the list manipulation. That means you can add ng-animate to the picker and get animation effects.
I hope that helps someone else looking at this question.
There were two problems with your code:
1) Your template had which being evaluated so your on was becoming the number 1, instead of the variable you wanted which is "which":
template: '<div><div ng-switch on="which"></div></div>',
2) When you used compile, you needed to pass in the $scope like so:
$compile(sel)($scope);
Here's an updated plnkr for you: http://plnkr.co/edit/Q6ViJBvkLwQRgUKYMfS9?p=preview

Angular.JS — A Directive, inside a directive, inside a directive, inside a directive. Scope issues

I have some issues regarding scope in nested directives. I have two directives: column and nested-menu. Their structure can be something like:
column
nested-menu
nested-menu
nested-menu
other content
nested-menu
other content
column
other content
The column has a variable to which all the nested-menu's should react. I have tried to make this work in several ways that I found Googling, such as broadcasting events from the column directive (for some reason, the nested-menu's only saw the event when I broadcasted it from $rootScope), setting a directive controller in column and storing the variable there (I can read it, but I can't $watch it).
It's important that both directives have an isolated scope, as they're supposed to be reusable in several areas, and sometimes even nested in themselves.
I have made a simplified Plnkr of a base structure, that's not working.
http://plnkr.co/edit/1GP7SKacO777og8PysNF
Thank you!
I am not sure how you want this to behave exactly. But here is a plunker that solves the two directives interacting with each other.
The nested-menu only expects column in its parent currently, But you could change it to expect another nested-menu in its parent if you wish.
Here is the working plunker. Hope this helps.
http://plnkr.co/edit/IAn9Ib8sSkQwKx6mpsm5?p=preview

Resources