I'm trying to use data binding inside a <script>.
<ol class="breadcrumb"></ol>
<div class=heading><h2>{{current.name}}</h2>
...
<script>
$(function(){
$(".breadcrumb").append('<li> Ledige stillinger</li>');
$(".breadcrumb").append('<li><a href=#!/categories/{{current.keyname}}>{{current.name}}</a></li>');
});
</script>
</div>
My result is:
Ledige stillinger (this is ok!) / {{current.name}} (here should it be the name, it works inside h2)
What am I doing wrong?
my answer would be to use AngularJS as it is intended and 1-way bind your DOM to the model values.
if there are multiple elements with the "breadcrumb" class then add these to a collection in your controller's scope and use ng-repeat directive to render them all out then append the "li" tags to this template.
Please see this plunkr example: http://plnkr.co/edit/0T6ldRzSTCnVIKnn3WRh
look at app.js and the following markup:
<ul class="breadcrumb">
<li>{{current.name}}</li>
</ul>
Related
I have created a dropdown list like feature using angualrjs directive, The directive is working somewhat but not in correct way I expected.
Following are the issues which I am facing.
The drop-down list alignment is correct for static but not for dynamic
I am not able to select any of the option list since getValue function which I have defined in the parent directive is not been invoked from the trancluded directive
Can anyone please tell me some solution for this
My code is as given below
PLUNKER
<div ng-controller="MainCtrl">
Static
<grant-parent ng-model="grand1">
<parent label="Parent1" value="12">
<child value="56" label="Child1">Child1</child>
<child value="57" label="Child2">Child2</child>
</parent>
<parent label="Parent1" value="13">
<child value="58" label="Child3">Child3</child>
<child value="59" label="Child4">Child4</child>
</parent>
</grant-parent>
Dynamic
<grant-parent ng-model="grand2">
<parent ng-repeat="parent in data" label="{{parent.parentName}}" value="{{parent.parentId}}">
<child ng-repeat="child in parent.childrens" label="{{child.name}}" value="{{child.id}}">{{child.name}}</child>
</parent>
</grant-parent>
</div>
Transclusion and ng-repeat have caused me headaches, and I thought it would be challenging, but the solution proves quite simple:
Remove the DOM manipulation from your link function and do the transclusion in the template!
I.e. <div ng-transclude></div> in the template of the parent and remove this line: elm.find('div').replaceWith(transclude()).
Forked plunk: http://plnkr.co/edit/UGp6D29yxnu0uJwD1BM2?p=preview
Now the markup comes out a bit different, the wrapper <div> still exists. Although there seems to be no visual difference, this may not be what you want. I do not think there is a sane way to get around this, so I would suggest altering the layout a bit: Why don't you place the children inside the parent <li>, e.g. as:
<li>
<b><a href='#' ng-click='getValue(optGroupLabel,optGroupValue)'>{{optGroupLabel}}<span class='value'>{{optGroupValue}}</span></a></b>
<div ng-transclude></div><!-- the div is now inside the li -->
</li>
This works in the plunker, but the markup is still invalid (<li> within <div>).
The best solution is to wrap the children in their own <ul>, i.e.:
<li>
<b><a href='#' ng-click='getValue(optGroupLabel,optGroupValue)'>{{optGroupLabel}}<span class='value'>{{optGroupValue}}</span></a></b>
<ul ng-transclude></ul><!-- The div is replaced with ul -->
</li>
This does not work in the plunk as it is, but should work with a little CSS tweaking.
Concerning getValue You have gotten wrong how isolated scopes and transclusion work. The grandParent directive defines the getValue method in its isolated scope. The transcluded things (the parent and child directives) get the outer scope, i.e. the scope of the MainCtrl. A solution is to move getValue() to the MainCtrl.
A better solution would be to pass a callback to the descendants of the grandparent, e.g. as scope: { assignValue: '&' }. But this solution cannot be implemented for the code in its current form because the grandparent does not directly include its children, so it cannot pass arguments to them.
The final solution - copied from the comments: move getValue to the controller of grandParent, have the parent and children require the grandparent and call that function. See http://plnkr.co/edit/pS9SspLaoPlqoWMYr8I0?p=preview
I have been learning angular and found this when trying to access the parent controller
http://jsfiddle.net/eqb23s8t/
I was expecting to access the same variable from the parent controller from inside the ng-repeat using the $parent so when one of the checkbox is pressed, all should be updated, but this is not true. Why ?.
<div ng-app ng-controller="ParentCtrl">
<ul>
<li ng-repeat="city in cities">{{city}}<input type="checkbox" ng-checked="$parent.somevar" /></li>
</ul>
</div>
First, your jsFiddle has a ChildCtrl defined but it will have no effect because you never use it. You can delete it.
Second, as described in the ngChecked documentation, there is a difference between ngChecked and ngModel:
https://docs.angularjs.org/api/ng/directive/ngChecked
If what you're expecting to happen is have all the checkboxes check/uncheck together, you probably want ngModel rather than ngChecked.
It's not clear from your question what you're actually trying to do, but here's a fork of your jsFiddle illustrating data sharing through a $parent variable:
http://jsfiddle.net/7jzyk7f6/
It just does the following:
<li ng-repeat="city in cities">{{city}}<input type="checkbox" ng-model="$parent.somevar" /></li>
to illustrate both concepts.
You are not bind a model for the view, which can reflect the changes. The current code just reads the model (in this case the somevar) state. Use ng-model instead of ng-checked. The angular will handle the rest:
HTML
<div ng-app ng-controller="ParentCtrl">
<ul>
<li ng-repeat="city in cities">{{city}}<input type="checkbox" ng-model="$parent.somevar" /></li>
</ul>
</div>
JS
function ParentCtrl($scope) {
$scope.cities = ["NY", "Amsterdam", "Barcelona"];
$scope.somevar = true;
}
http://jsfiddle.net/eqb23s8t/4/
In this case, you need to use ngModel (two-way binding) instead of ngChecked (one-way binding):
ng-model="$parent.somevar"
See JSFiddle
I'm also totally newbie in Angular so I can be wrong. But I see few... things in your code. First of all ChildCtrl is not used at all. Second, it looks like only ng-model directive applied two-way binding to checkboxes. Yet ng-checked used just to add|remove checked attribute.
And js-fiddle
Sir please use ng-model to refer scope of the parent.
here is what i have created demo for you [demo][1]
[1]: http://jsfiddle.net/nwg7bwLx/
Let's say I have a list of links and I want each of them to change the DOM on the current page
using ng-click and templating, how would I do that?
Edit: I guess what I am trying to understand is how to move as much of the logic away from the .html file and into my app.js file. I'm a little new to JS and Angular and don't know where or how to pass "active" to choose what I'd like to place inside
For example:
<ul>
<li>
<h1>foo1</h1>
</li>
<li>
<h1>foo2</h1>
</li>
<li>
<h1>foo3</h1>
</li>
</ul>
<active></active>
Where the active element displays only what template is set to the active one.
ie; the template associated with foo1 is displayed, and then if foo2 is clicked the template for foo2 replaces foo1
I am not sure what is the implementation of <active>, but you can use ng-include to implement what you are expecting
<active ng-include='active'></active>
Now create a client side or server side template with the name which matches variable active defined on scope and corresponding template would get loaded
A template definition could be like
<script type="text/ng-template" id="foo1">
<!-- html template for foo here-->
</script>
See ng-include documentation.
You could use ng-show/ng-hide. Basically something like this.
<div ng-show="foo1">
<p> This will only show when foo1 is true on your scope.
</div>
<div ng-show="foo2">
<p> This will only show when foo2 is true on your scope.
</div>
<div ng-show="foo3">
<p> This will only show when foo3 is true on your scope.
</div>
Also if you're wanting to keep the logic of the active = 'foo1' just change up the logic in the ng-show. Usually you want to keep logic out of the view though, so move that to your controller.
I can't get my head wrapped around solving the following problem using angularJS.
I have a list view containing different kinds of data elements. Each element in itself is a view and has its own controller.
Now I want to iterate over this Array of the data items and based on recordType attribute, I want to initialize a controller with a template and finally add it to the list view.
At the moment I am using ng-include="item.recordType+'.html'" to dynamically load the template and the template itself has an ng-controller tag which loads the relevant controller. But I am not sure if this is the best approach.
<div class="data-item" ng-repeat="item in container.record_collection">
<div ng-include src="item.tRecordType + '.html'"></div>
</div>
Say record-type is apples
<script id="apples.html" type="text/ng-template">
<div ng-controller="ApplesController as apple">
<!-- ... HTML TEMPLATE ... -->
</div>
</script>
is it somehow possible to render the template in a polymer element dynamically at runtime or when some light-dom elements are available?
I have the following situation:
index.html
<mega-menu>
<span class="menuTriggerText">Open Menu</span>
<ul class="test">
<li>TEST1</li>
<li>TEST2</li>
</ul>
<ul class="test">
<li>TEST1</li>
<li>TEST2</li>
</ul>
</mega-menu>
in my polymer-element.html i want to do something as follows:
<template>
<template repeat="{{temp}}"><p>I want to try this</template>
</template>
Polymer('mega-menu, {
created:function(){},
ready: function(){
//getting markup from light-dom
this.temp = document.getElementsByClassName('test');
},
attached:function(){},
detached: function(){},
attributeChanged: function(attrName, oldVal, newVal){}
});
Now, my question is - how do i get this to work? do i need to bind something on my template? or do i need some kind of event-listener or observer on something?
Thanks, Gbeschbacher
This is precisely what content insertion points are for. You can select top-level light DOM markup to render at specific locations in the Shadow DOM. <content select=""></content> takes a CSS selector and grabs nodes from the light DOM.
Your example would be:
<polymer-element name="mega-menu" noscript>
<template>
<content select=".test"></content>
</template>
</polymer-element>
You should not need to pry into the light DOM like this for such a simple case, but for the sake of completeness, we can get your example working with a few important tweaks:
document.getElementsByClassName('test') looks for nodes in the entire document. This is not what you want. You only want children of <mega-menu>. Instead of document use this (e.g. this.querySelectorAll('.test')).
You're giving <template repeat="{{temp}}"> a NodeList. It won't be able to stamp that out. It expects an Array. Something like this.temp = [].slice.call(this.querySelectorAll('.test')); would work.
http://jsbin.com/balodowi/2/edit