I am working on an angular directive and i am trying to prepend an element.
.directive('someDirective', function($compile){
restrict: "E",
scope:{
items="#"
}
link: function(scope,elem,attrs){
// selector
angular.element(div > ul).prepend($compile('<p> Hello World <p>') (scope))
},
template:`
<div class="container">
<ul class="foo">
<li ng-repeat="item in items"> {{ item }} </li>
</ul>
</div>`
});
it appends inside ul. How am i supposed to append the element after the ul tag?
<div class="container">
<ul class="foo">
<!-- prepend element goes here :( -->
<li ng-repeat="item in items"> {{ item }} </li>
</ul>
<!-- I want the prepended element to go here -->
</div>`
i believe there is something wrong with my selector.
To place an element after another element, and not inside it, you can use after(), it's part of Angulars jqLite as well
angular.element(div > ul).after($compile('<p> Hello World <p>') (scope))
Related
I am creating this grocery list application with Angular4, so I need the user to be able to click on an item and it will be added to the bookmarked section.
I used Jquery to access the innerHTML of the li when we hover over it, take the value and add it into the bookmark array, but the innerHTML keeps returning "undefined".
javascript:I used this bit to get the innerHTML
$('li').hover(function(){
console.log($(this).innerHTML);
});
html:I've used *ngfor to spit out all the list items
<div class="col-m-6">
<h3 class="text-primary">All Items</h3>
<ol>
<li class="listItem" *ngFor="let g of groceries">{{g}}</li>
</ol>
</div>
In the console it keeps showing "undefined", please help. TIA
Avoid using Jquery or any other way of direct DOM manipulation while developing SPA.
Try following
Template
<li class="listItem" *ngFor="let g of groceries" (click)="onClick(g.id)">
{{g}}
</li>
Component
onClick(id) {
//add to bookmark
}
Solution1: Use html() jQuery.
Stack Snippet
$('li').hover(function(){
console.log($(this).html());
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="col-m-6">
<h3 class="text-primary">All Items</h3>
<ol>
<li class="listItem" *ngFor="let g of groceries">{{g}}</li>
</ol>
</div>
Solution2: Use this.innerHTML.
Stack Snippet
$('li').hover(function(){
console.log(this.innerHTML);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="col-m-6">
<h3 class="text-primary">All Items</h3>
<ol>
<li class="listItem" *ngFor="let g of groceries">{{g}}</li>
</ol>
</div>
you have need to use jQuery html() method to gett innerHTML.
So, use the following:
$('li').hover(function(){
console.log($(this).html());
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="col-m-6">
<h3 class="text-primary">All Items</h3>
<ol>
<li class="listItem" *ngFor="let g of groceries">{{g}}</li>
</ol>
</div>
For jQuery to work on dynamic elements you should be doing it this way
$(document).on('hover', 'li', function(){
console.log($(this).innerHTML);
});
I am new to AngularJS. I want to create links for elements in the array. Suggest me some code or descriptives.
app.js
app.controller('ItemsController', function($scope) {
$scope.message = 'Items are displayed';
$scope.items=['Appliances','Books','Cosmetics','Home & Furniture','Mens','women','kids'];
});
items.html
<div ng-controller="ItemsController">
<p><h1>Type a letter in the input field:</h1></p>
<p><input type="text" ng-model="test"></p>
{{message}}
<ul><h2>
<li ng-repeat="x in items| filter:test">
{{ x }}
</li>
</h2></ul>
</div>
Here is the sample output for the above code. Items displayed in the output should be links.
If you are using routing then just create an anchor tag in the li.
<ul>
<h2>
<li ng-repeat="x in items| filter:test">
{{x}}
</li>
</h2>
</ul>
In the route configuration, just handle the specific route pertaining to the item. Like if you want to display the details for the item.
myApp.config(['$routeProvider',function($routeProvider){
$routeProvider.
when('/details/:item',{
templateUrl:'partials/details.html',
controller: 'DetailsController'
}).
otherwise({
redirectTo : 'yourdefaultpath'
})
Item shall be available in your controller as a routeParam and then you can display your data accordingly.
Hope this helps.
You can use ui-sref and declare your items as states using ngRoute in your app, this is how would be your code:
<ul>
<li ng-repeat="x in items| filter:test">
<a ui-sref="{{x}}"><h2>{{ x }}</h2></a>
</li>
</ul>
Update your JS to add the states, like this:
app.config(function($stateProvider) {
$stateProvider.state('Appliances', {
url: 'Appliances',
templateUrl: 'app/views/appliances.html'
});
});
I got an workaround here and need some help. It is a tree of categories. Some categores can be chosen by a checkbox.
I thougt the cleanest way to do that is via direction. On a <li kw-category-node> element put a on('click', function()) handler, which then does the choosing work (add object to data etc.).
So I came up with this HTML
<script type="text/ng-template" id="category_renderer.html">
<div ng-if="true == true" ng-mouseenter="over = true" ng-mouseleave="over = false">
<input type="checkbox"
ng-model="assignedCategories[category.category_id]"
ng-if="category.childs.length == 0"
ng-click="toggleCategory(category)">
</input> {{ category.name }}
<a href ng-if="over" ng-click="categories.remove(category)">
<small> <i class="fa fa-times"></i> Entf </small>
</a>
</div>
<ul class="list-unstyled">
<li ng-repeat="category in category.childs"
ng-include="'category_renderer.html'"
kw-category-node>
</li>
</ul>
</script>
<ul class="list-unstyled" kw-category-tree>
<li ng-repeat="category in categories.tree"
ng-include="'category_renderer.html'"
kw-category-node>
</li>
</ul>
And a directive like that
admin.directive('kwCategoryNode', ['$interval', 'dateFilter', function($interval, dateFilter) {
function link(scope, element, attrs) {
element.find('input').on('click', function() {
alert("wow, what a click!");
});
}
But element.find("input") wont give me that input element. Maybe the DOM is not loaded completly or I'm just in tilt.
Thanks
So I'm trying to create a simple tab system in angularjs, but whenever I try to bind data on ng-click on the a or li tags of my template I get this error:
Syntax Error: Token '' {1} at column {2} of the expression [{3}] starting at [{4}].
I been searching for hours can't figure out what's causing the problem
here's my code:
<div id="tabs">
<ul>
<li ng-repeat="file in files" ng-click="tab = {{$index}}">
{{file.file_name}}.{{file.file_extension}}
</li>
</ul>
</div>
<!-- tab container -->
<div class="tab-content">
<div class="tab" ng-repeat="doc in files" ng-show="tab == {{$index}}">
{{doc.file_name}}.{{doc.file_extension}}
</div>
</div>
I have tried wrapping {{$index}} in single quotes, that fixes the problem but the tabs don't work when clicked.
You could move this out of the inline logic and into a function, for example $scope.setTabIndex, like so:
$scope.setTabIndex = function(index) {
$scope.tab = index;
}
And then in your markup:
<li ng-repeat="file in files" ng-click="setTabIndex($index)">
And for the ng-show, just remove the curly braces around $index:
<div class="tab" ng-repeat="doc in files" ng-show="tab == $index">
Here's as jsBin
I have 3 different directives, <one>, <two>, <three>.
I want to loop through their ids and insert them in an ng-repeat
<ul>
<li ng-repeat="panel in panels">
<panel>
<!-- panel.id would give me "one", "two" etc. -->
<!-- First insert <one> then <two> etc -->
</panel>
</li>
</ul>
The resulting html I would like to achieve then would be:
<ul>
<li>
<panel>
<one></one>
</panel>
</li>
<li>
<panel>
<two></two>
</panel>
</li>
<li>
<panel>
<three></three>
</panel>
</li>
</ul>
And since each has its template:
<ul>
<li>
<div class="panel">
<div id="one">
</div>
</div>
</li>
<li>
<div class="panel">
<div id="two">
</div>
</div>
</li>
<li>
<div class="panel">
<div id="three">
</div>
</div>
</li>
</ul>
I am not sure how to do this? Is this possible? do I have to ng-compile to have a directive inside a directive?
Should I use just one directive and use an ng-switch?
Am I missing a more straightforward approach?
I know this works:
make a <panel-content> directive.
I include this on the <panel> directive:
make an
<ng-switch="panel.id">
<ng-switch-when="one">
<ng-switch-when="twp">
<ng-switch-when="three">
</ng-switch>`
But it seems cumbersome.
The way that I normally do this is use one directive that picks the specific directive in the link function. That prevents all of the ng-switch bloat.
html
<panel type='one'></panel>
<panel type='two'></panel>
js
angular.module('app').directive('panel', ['$compile', '$injector', function ($compile, $injector) {
return {
restrict: 'E',
scope: {
type: '='
},
link: function ($scope, element, attrs, vm) {
var template;
switch($scope.type){
case 'one':
template = '<one></one>';
break;
case 'two':
template = '<two></two>';
break;
}
element.html(template);
$compile(element.contents())($scope);
}
};
}]);
Here's a fiddle showing this in action: http://jsfiddle.net/7cufjqs3/1/
If you're willing to live with an extra div between your directive and panel element I created a dynamic directive that knows nothing about the name of the element, and creates it dynamically:
Usage:
<li ng-repeat="panel in panels">
<panel>
<dynamic-directive element="panel.id"></dynamic-directive>
</panel>
</li>
Directive:
myApp.directive('dynamicDirective', function($compile) {
return {
restrict: "E",
replace: true,
template: "<div></div>",
scope: {
element: "="
},
link: function(scope, element, attrs) {
var elm = '<' + scope.element + '></' + scope.element + '>';
element.html(elm);
$compile(element.contents())(scope);
}
}
});
Fiddle
I think a the switch is the best approach because it's most readable in your html
<ul>
<li ng-repeat="panel in panels">
<panel ng-switch on="panel.id">
<div ng-switch-when="one"><one>1</one></div>
<div ng-switch-when="two"><two>2</two></div>
<div ng-switch-when="three"><three>3</three></div>
</panel>
</li>
</ul>
http://plnkr.co/edit/ygy6coKCyQNGBoKmSES0?p=preview