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.
Related
I have two custom element directives:
<my-directive-parent></my-directive-parent> //only one
and
<my-directive-child></my-directive-child> //variable count
The my-directive-parent directive has its own controller and templateUrl properties defined in its directive definition object. The my-directive-child directive has its own link, scope, templateUrl and require properties defined in its directive definition object. The fourth parameter passed into the link function is the parent my-directive-parent's controller. This is working as expected.
Based on user input, instances of my-directive-child are appended to or removed from the parent my-directive-parent DOM via the my-directive-parent's controller. Since I'm using ngView for the top-level page, changing pages results in Angular automatically cleaning up the various directives and their controllers of the top-level page. Upon returning, the controller for the page re-runs, but the user appended views do not show up (since they were previously wiped out automatically by Angular). I'm using a service which holds the data representing the collection of my-directive-child instances that were previously added.
My issue lies in restoring the my-directive-child directives based on this cached service data. Currently, when the my-directive-parent directive's controller is run, I'm getting the service data array that represents the instances to be added, looping through it, and adding a new my-directive-child instance to the DOM. This is working, but upon restoring each instance I need to pre-populate it with data that was previously entered by the user (of which is recorded in the service). Currently, when adding to the DOM this way each instance is in a "blank" state instead of a desired pre-populated state.
So I have the data needed to recreate the child directive instances, but I'm unable to pre-populate them with the necessary data.
I've tried to place a custom attr on the my-directive-child in an effort to forward the data to the instance's scope, but I learned from Angular's API docs that:
The new scope rule does not apply for the root of the template since the root of the template always gets a new scope
Questions:
Is my approach wrong? What should I be doing?
Is there a way to pass attrs defined on the actual element directive into the directive's scope that represents the inner template HTML?
How do I ensure a custom directive within a custom directive properly pre-populates itself?
Thank you in advance for any ideas, answers, or thoughts that might lead to a solid solution.
My app have multiple bootstrap tables and i want to create a global angularjs directive for sorting these tables to use this custome directive.
I have tried few but they don't help me enough what i want.
Please find plunk below for example.
http://plnkr.co/edit/BFkWWWtuZK4x6dHiEy3I
In the above example is not sorting as the scope is not updated.
So your directive isn't manipulating the outside scope. It can't do that because it doesn't have access to the variables in the parent scope because javascript is copy by value. You can manipulate what you are passed, but you can't manipulate the value of variable that was passed to you. So angularjs wants you to put objects between you and the references you are binding between so manipulations in across isolated scopes will propagate back to the caller. So if you modify your app to use that it works.
http://plnkr.co/edit/6sqQZk
Now it's a bit messy for my tastes. I'd probably move the whole table definition into the directive, and let it handle the whole thing. It would also make it easier to setup a sorting table without all of the plumbing, but that's up to you.
I haven't been able to find anywhere else that really helps me understand my Angular problem here but I suspect it has something to do with inheritance that I haven't completely grasped yet.
I'm doing an ng-repeat of a custom directive and seeing strange behavior when attempting to update the collection from a resource. Here is the plnkr:
http://plnkr.co/edit/QXAFvQix8oUiVMlMuEXw
To see what the issue is, click on the 'Finish Registration' button which retrieves the json from the resource and replaces the current collection. What I expect is for the cards to be replaced by updated cards, but what is happening is that the first 2 cards seem to no longer be bound to the scope (or are somehow zombified) and 2 new cards are added. Each subsequent update updates the new cards as expected. What am I missing?
You are running into an issue with the isolated scope accidentally leaking into other directives defined on the same element.
However, this has been addressed and fixed in Angular v1.2.4 in this commit.
Hence, this version (with only Angular updated) works: http://plnkr.co/edit/kufU5fI90j2lj2jdyLBx?p=preview
The way to write it such that it is AngularJS version agnostic is keeping the relationship between the scopes perfectly clear by nesting the directives:
<div ng-repeat="student in currentUser.studentCollection">
<div student-card
student="student"
unit-schools="unitSchools"></div>
</div>
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.
I'm building a complex, variable layout with infinite scroll UI in AngularJS.
Think something like Flipboard with a load of repeating data items, each item containing the same thing (title, description, image etc). Each item is pre-loaded into JSON, sorted and then organised into a series of pages, selected from a series of variable layouts. Each page has a variable number columns and each column a variable number of rows.
In order to achieve this, I'm using multiple Directives for each page layout, compiled at run time. Inside each layout Directive, I'm then building a variable number of columns, each of which contains an ng-repeat for the variable number of rows. Each row can be a different Directive, depending on how it needs to be styled. Again, all of this is happening at runtime.
I'm 99% of the way there.
The Directives are being compiled correctly and calling up the correct column Directives, which in turn are compiling the correct number of rows. Once we get to the row/item level, I'm using a Service which brings back the correct Directive for each item. The reason I choose the Service approach is that I want the items to be reused inside other modules.
The problem I'm having, is that once the page layout is compiled, it sets up the columns and then the rows but does not execute the ng-repeat. I need to get the ng-repeat to loop and also call the specific Directives I use for each item.
I think is a problem to do with $compile and what Angular knows about the DOM. Maybe I need to do a $compile or $apply at some stage to get the ng-repeat to kick in and bind the final Directives to the data items.
**
Side note: if I don't use a Service, but simply use define each layout Directive with a templateUri it works perfectly!
I can go with this approach, but ideally, I'd like to get away from downloading a bunch of templates at runtime. Also, by passing parameters into a Service, I can design more layouts, much quicker and easier than having to build individual template files.
I've set up a JS fiddle with quick example of how I'm approaching all of this:
http://jsfiddle.net/joecarney/vE3Ls/6/
Some SO required code just to post this comment:
<div ng-app="app" ng-controller="appPageController">
<div>
<div my-page></div>
</div>
</div>
If you use scope: {} in a directive it creates a new scope so your directives will not have access to controller scope unless you allow it, which you started out doing but appears you then copied and pasted the same thing for all :)
The directive compiling items in ng-repeat had no access to items. I removed scope from directives and used the attrs value to access the attributes
http://jsfiddle.net/vE3Ls/7/