I would like to achieve the following (which does not work as written):
<div ng-repeat="product in products">{{product.headline}}</div>
<div>{{product.text}}</div>
I only first see all headlines, then all texts below each other. How can refer to product again on an additional div element?
There is a nifty feature in Angular whereby some directives, like ng-repeat, support spanning across multiple elements:
<div ng-repeat-start="product in products">{{product.headline}}</div>
<div ng-repeat-end>{{product.text}}</div>
You can also create custom directives that support this functionality. Here's a snippet from Angular docs:
multiElement
When this property is set to true, the HTML compiler will collect DOM nodes between nodes with the attributes directive-name-start and directive-name-end, and group them together as the directive elements. It is recommended that this feature be used on directives which are not strictly behavioural (such as ngClick), and which do not manipulate or replace child nodes (such as ngInclude).
Related
I am working on my first angular directive and still getting my head around the concepts and what's possible with directives. As I've been researching the best way to tackle this problem I haven't been able to identify an example that addresses what I'm trying to do, so thought I would ask for some help from the experts here.
I have an array of objects that are one of three types.
I would like to use the ng-repeat directive to iterate through this array and display the objects on the page.
Each object type has a different view associated with it as each object shares some properties, but also have unique properties.
I would like to set up a directive that displays the correct view based on the objective type.
So the logic would work something like the following:
<div ng-repeat="item in dataset">
<the-smart-directive>item</the-smart-directive>
</div>
One idea would be to have one directive where I determine the templateUrl based on the object type and then have a unique template for each of the objects.
Another idea would be to have a parent directive and then three other directives (one for each object type) and the parent directive would insert the correct object type directive (this is the idea that seems like the better approach, but I'm not sure how to actually implement this idea).
I'd love some help in understanding the best way to tackle this and how to implement. If you could provide some example code that would be wonderful and get me started on the right path.
Thanks for your help!
The way we are using it is with ng-switch inside the ng-repeat.
<div ng-repeat="item in dataset" ng-switch="item.type">
<directive-one ng-switch-when="1">
</directive-one>
<directive-two ng-switch-when="2">
</directive-two>
<directive-three ng-switch-when="3">
</directive-three>
</div>
I am trying to create an angular-js directive that encapsules editing a list of items: It should iterate over a list, repeating the wrapped element of the directive for every item and add some controls to each line (deleting elements, moving elements around, ...). Ideally I would like to use the directive like this:
<edit-list list="mylist">
<input ng-model="item.name">
<input ng-model="item.location">
</edit-list>
where the directives template should be like this (as demonstration I added a button for deleting items):
<div ng-repeat="item in list track by $index">
<span ng-transclude></span><button ng-click="delete_item($index)">
</div>
However, I can't get this to work. I tried to adapt this answer which manages to repeat the wrapped element over a list, however the plunker does not work anymore with modern angularjs versions (see my forked plunker which changes only the version of angularjs).
Nevertheless, here is a plunker tries to implement what I want to accomplish, but failes: It seems like the transcluded element can't see the item anymore. This makes sense given the documentation for ng-transclude, but I could not figure out how to make the wrapped element see the scope of the directive again.
I've updated your plnkr here http://plnkr.co/edit/GZsfp0HaeAVg5NjMBtGC?p=preview and made some changes:
Your goal is to ng-repeat over a list. There is no need for ng-transclude since you already binding your list to your directive.
I removed the reference to ng-transclude in your directive
I amended your delete method to pluck the proper item from the list.
Simple question regarding arguments for AngularJS directives within markups. Let's consider the following markup that has it's own directive.
<div selectbox resource="http://resource.org/asset/1">
</div>
we are passing an argument called 'resource' - and it's ok, but just wanted to ask as it's recommended to use in HTML5 data-* prefixed attributes is it better to write
<div selectbox data-resource="http://resource.org/asset/1">
</div>
which convention is better and why?
Better use custom html attributes with data- prefix, first of all it's described as standart for custom attributes and if you want to validate your html all custom attributes without data- prefix will be invalid.
From Angular Docs
If you want to use an HTML validating tool, you can instead use the data-prefixed version (e.g. data-ng-bind for ngBind).
More info:
Post about data-*
Use with css3
i'm using ng-repeat to display some array values (messages). How do i get the corresponding DOM element after pushing it to the messages array?
I want to add and remove a class(es) from the added dom element.
Thank you,
Bernhard
The Angular way is not to directly manipulate the DOM but to use the directives provided to you by the framework. To change the CSS classes applied to an element, use ngClass, ngClassEven, and ngClassOdd.
<div ng-repeat="item in items">
<span ng-class="{active: isActive(item)}">{{item}}</span>
</div>
The parameter to ngClass is a JavaScript object which keys are the names of the CSS classes, and values are expressions. For each key-value pair, if the expression results in true, the class is added, otherwise it is removed.
ngClassEven and ngClassOdd can be used to apply classes only to even or odd elements of the repetition.
Several times when creating or customizing a directive (either my own directive or for example https://github.com/dpiccone/ng-pageslide) I get a point where all the display logic is controlled by a single css class. At that point the directive boils down to adding and removing a single class. So instead of using a new directive I can simply use the ng-class directive (see an example here: https://gist.github.com/Hypercubed/8f40556eb0f6eddbcca3). Is there an advantage to the custom directive approach vs the ng-class/CSS styles approach? I guess the custom directive doesn't depend on $animate? Am I just doing it wrong?
Sorry for another directive vs. XXX question.
I think you're failing to see the forest for the all tress. You're focusing on a very minute detail and missing the larger picture. Directives are more than simply applying styles. I think an example is best. For example, take the rating directive. If you wanted to render a star rating model it might look like this:
<div ng-rating="album.rating" max="5"></div>
That may add the following to the DOM:
<ul class="inline">
<li ng-repeat="i in max">
<i ng-class="{ 'icon-start-empty': i > rating, 'icon-star': i <= rating }"></i>
</li>
</ul>
Under the covers ng-class it utilized, but that is only a part of the logic encapsulated in the rating directive. It allows the user to configure how many stars the rating is out of, and renders the same number of li elements. Then because you wrote a directive it allows you to reuse this logic where ever it's required. Using ng-class only works in that 1 location. If you want to do the same thing you're copying code which is a sign maybe you want to wrap that logic up in a directive.