Angular directive is not working for the following case. In the my following angular application I have two kinds of item I wish to display which are stored in controller.
To display them I have created the directives for both cases, and iterating over list with ng-repeat, but the items are not being rendered.
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<style media="screen">
.selected {
background: #cdcdcd;
}
</style>
</head>
<body ng-app="myApp">
<div ng-controller="ListController as listctrl">
<div class="" ng-repeat="item in listctrl.items">
<itemtype1 ng-if="item.type_ === 'type1'" val="item.val"></itemtype1>
<itemtype2 ng-if="item.type_ === 'type2'" val="item.val"></itemtype2>
</div>
</div>
<script type="text/javascript">
angular
.module('myApp',[])
.controller('ListController', function($scope) {
var listctrl = this;
listctrl.items = [];
listctrl.items.push({'val':'A', 'type_': 'type1'});
listctrl.items.push({'val':'B', 'type_': 'type2'});
listctrl.items.push({'val':'C', 'type_': 'type1'});
listctrl.items.push({'val':'D', 'type_': 'type2'});
})
.directive('itemtype1', function() {
return {
template: '<strong>{{$scope.val}}</strong>',
restrict: 'E',
scope: {
val: '='
},
link: function postLink(scope, element, attrs) {
}
};
})
.directive('itemtype2', function() {
return {
template: '<i>{{$scope.val}}</i>',
restrict: 'E',
scope: {
val: '='
},
link: function postLink(scope, element, attrs) {
}
};
});
</script>
</body>
</html>
My first guess, just glancing through it, is that you should change the following:
template: '<strong>{{$scope.val}}</strong>'
to this:
template: '<strong>{{val}}</strong>'
Related
I'm trying to modify the input element using a custom AngularJS directive. Basically I want to replace any <input type="country"> fields with a country drop-down.
But the directive doesn't seem to work with input fields. If I change it to any other tag, it works?
Here is the code:
angular.module('plunker', [])
.controller('MainCtrl', function ($scope) {
$scope.name = 'World';
});
angular.module('plunker')
.directive('input', function() {
return {
restrict: 'E',
scope: {ngModel: '=?'},
link: function(scope, elem, attr) {
if(attr.type === 'country') {
elem.html('html code for select');
alert(elem);
}
}
};
});
<!doctype html>
<html ng-app="plunker" >
<head>
<meta charset="utf-8">
<title>AngularJS Plunker</title>
<link rel="stylesheet" href="style.css">
<script>document.write("<base href=\"" + document.location + "\" />");</script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
Name: <input type="country" ng-model="name"/> <br/>
</body>
</html>
Can someone please explain and suggest a workaround?
P.S. I've also tried doing this in the directive, but it doesn't work either!
replace: true,
template:'<div>hello</div>'
P.S. I know I can use a ng-country or some other custom tag but I want to change input tag only because I want learn why this is happening or possibly find out what I'm doing wrong?
Latest Update:
Your code is just setting the html on the element, instead of replacing it. You would want to use replaceWith instead like this:
var app = angular.module("TestApp",[]);
app.controller("TestController", function($scope){
$scope.message = "Input Directive Test"
});
app.directive("input", function() {
return {
restrict: "E",
link: function(scope, elem, attr) {
if(attr.type === "country") {
var select = angular.element("<select><option>USA</option></select>");
elem.replaceWith(select);
}
}
}
});
And here's the JSBin: https://jsbin.com/juxici/4/edit?html,js,output
Initial Version of my answer:
Here's an example that works without any issues when 'replace' and 'template' are used. I'm not checking for type and such, but you could do that in the linker code.
JSBin: https://jsbin.com/juxici/2/edit?html,js,output
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script>
</head>
<body ng-app="TestApp">
<div ng-controller="TestController">
<h2>{{message}}</h2>
<input type="country" ng-model="name"/>
</div>
</body>
</html>
Javascript:
var app = angular.module("TestApp",[]);
app.controller("TestController", function($scope){
$scope.message = "Input Directive Test"
});
app.directive("input", function() {
return {
restrict: "E",
replace: true,
template:"<select><option>USA</option></select>"
}
});
I am getting the error: angular.js:10627 Error: [$parse:syntax]
when interpolating a value in the template, only when it's in the attribute of an element.
template field_message.html:
<input type="number" ng-model="{{ model }}">
<div>{{ model }}</div>
directive:
myApp.directive('ivInput', function(){
return {
restrict: 'EA',
templateUrl: "field_message.html",
scope: {
model: '#ngModel'
}
};
});
view html:
<div iv-input="flatK" ng-model="modelname"></div>
In the template, the first instance of {{ model }} causes a parse error. If I remove this, the other instance correctly renders out the model name. Is there a way to get the model name into the value for ng-model on the input element?
Working absolutely fine.
<!DOCTYPE html>
<html lang="en" ng-app="app">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.js"></script>
<meta charset="UTF-8">
</head>
<body ng-controller="ctrl">
<div iv-input="flatK" ng-model="modelname"></div>
<span>{{modelname}}</span>
<script>
var app = angular.module('app', []);
app.directive('ivInput', function(){
return {
restrict: 'EA',
template: "<input type='number' ng-model='ngModel'>"+
"<div>{{ model }}</div>",
scope: {
ngModel:'='
}
};
});
app.controller('ctrl',function($scope){
$scope.modelname=23;
} )
</script>
</body>
</html>
I want to bind some dynamic content, loaded by jQuery, to Angular but i couldn't get it work.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript" src="bower_components/jquery/dist/jquery.min.js"></script>
<script type="text/javascript" src="bower_components/angular/angular.min.js"></script>
<script type="text/javascript">
var module = angular.module('ctrl', []);
module.directive('helpMe', function() {
return {
restrict: 'E',
template: '<div><button ng-click="clicker()">Click 1</button><button ng-click="create()">Create</button><div ng-hide="true">FooBar</div></div>',
controller: ['$scope', function($scope) {
$scope.clicker = function () {
console.log('Clicked...');
};
$scope.create = function () {
$('#foo').contents().clone().appendTo('#bar');
}
}]
}
});
</script>
</head>
<body ng-app="ctrl">
<div id="foo">
<help-me></help-me>
</div>
<div id="bar">
</div>
</body>
If i click the "Click 1" button, the console logs it. If i click the "create" button, a new set of buttons appears. But the new buttons don't work. I could not find out how to get this work. Any ideas?
You need to call $compile on the HTML string before inserting it into the DOM so that angular gets a chance to perform the binding.
$scope.create = function() {
var clone = $('#foo').contents().clone();
$compile(clone)($scope);
$('#bar').append(clone);
}
check this plnkr
Try this it will work:-
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript" src="bower_components/jquery/dist/jquery.min.js"></script>
<script type="text/javascript" src="bower_components/angular/angular.min.js"></script>
<script type="text/javascript">
var module = angular.module('ctrl', []);
module.directive('helpMe', function() {
return {
restrict: 'E',
template: '<div><button ng-click="clicker()">Click 1</button><button ng-click="create()">Create</button><div ng-hide="true">FooBar</div></div>',
controller: ['$scope','$compile' function($scope,$compile) {
$scope.clicker = function () {
console.log('Clicked...');
};
$scope.create = function () {
$('#foo').contents().clone().appendTo('#bar');
$compile($('#bar'))($scope);
}
}]
}
});
</script>
</head>
<body ng-app="ctrl">
<div id="foo">
<help-me></help-me>
</div>
<div id="bar">
</div>
</body>
This directive fires when ng-repeat finishes using scope.$last:
simpleSearchApp.directive('afterResults', function($document) {
return function(scope, element, attrs) {
if (scope.$last){
scope.windowHeight = $document[0].body.clientHeight;
}
};
});
I'm trying to update $scope.windowHeight with a new value but I can't access $scope inside the directive.
My ng-repeat HTML with directive:
<div ng-show="items" class="ng-cloak" ng-repeat="item in items" after-results>
{{item}}
</div>
Honestly saying I have also not understand why it's not updating. But the the alternate approach to update variable in controller is to define a function wich update the variable and call that function in controller from directive. Please take a look at the following example it might help you.
angular.module('app',[]).controller('MyController',['$scope',function($scope){
$scope.windowHeight = 0;
$scope.updateWindowHeight = function(height){
$scope.windowHeight = height;
}
}])
.directive('afterResults', function($document) {
return function(scope, element, attrs) {
if (scope.$last){
scope.windowHeight = $document[0].body.clientHeight;
scope.updateWindowHeight( scope.windowHeight);//calling function in controller
}
};
});
<!DOCTYPE html>
<html ng-app="app">
<head>
<script data-require="angular.js#1.4.1" data-semver="1.4.1" src="https://code.angularjs.org/1.4.1/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-controller="MyController">
<div class="ng-cloak" ng-repeat="item in [1,2,3,4,5]" after-results="updateWindowHeight()">
{{item}}
</div>
<hr/>{{ "$scope.windowHeight ="+windowHeight}}
</body>
</html>
can you please tell me how to make dirctive in angular js .I need to use owl carousel plugin in js as I did in jqm fiddle http://jsfiddle.net/ezanker/o9foej5L/1/
.I need to make same thing in angular using directive can you please tell me how I will implement this using directive
http://plnkr.co/edit/4ySYwsqrBKUJUj6MwoRY?p=catalogue
<!DOCTYPE html>
<html>
<head>
<link data-require="bootstrap-css#3.x" data-semver="3.2.0" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" />
<link data-require="bootstrap-css#3.x" data-semver="3.2.0" rel="stylesheet" href="http://www.owlgraphic.com/owlcarousel/owl-carousel/owl.carousel.css" />
<link data-require="bootstrap-css#3.x" data-semver="3.2.0" rel="stylesheet" href=" http://www.owlgraphic.com/owlcarousel/owl-carousel/owl.theme.css" />
<script data-require="angular.js#*" data-semver="1.3.0-beta.5" src="https://code.angularjs.org/1.3.0-beta.5/angular.js"></script>
<script data-require="ui-bootstrap#0.10.0" data-semver="0.10.0" src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.10.0.js"></script>
<link href="style.css" rel="stylesheet" />
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="script.js"></script>
<script src="http://www.owlgraphic.com/owlcarousel/owl-carousel/owl.carousel.js"></script>
</head>
<body>
<div id="owl-demo">
<div class="item"><p>one</p></div>
<div class="item"><p>two</p></div>
<div class="item"><p>three</p></div>
<div class="item"><p>four</p></div>
</div>
</body>
</html>
You can use a directive like this:
app.directive('owlCarousel', function() {
return {
restrict: 'A',
scope: {
owlOptions: '='
},
link: function(scope, element, attrs) {
$(element).owlCarousel(scope.owlOptions);
}
};
});
And on the HTML add it as an attribute:
<div owl-carousel owl-options="owlOptions">
...
</div>
Demo
Here is my general solution. This works with ngrepeat and with refresh data of the scope. The trick is add a directive for the last item, so the init will be fired when the last item is in the dom.
<div owl-slides-count="3" owl-carousel="">
<div ng-repeat="post in posts" owl-carousel-item="">
...
</div>
</div>
... the js
.directive('owlCarousel', ['$timeout', function ($timeout) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
scope.initCarousel = function () {
// hacky ondomready
$timeout(function hackyDomReady() {
// if is already initialized destroy and re create it
// $(element).data().owlCarousel <- owl 2
if ($(element).data('owlCarousel')) { // <- owl 1
// $(element).trigger('destroy.owl.carousel'); // <- owl 2
$(element).data('owlCarousel').destroy();// <- owl 1
}
$(element).owlCarousel({
autoPlay: 10000,
navigation: true,
items: attrs.owlSlidesCount
});
});
};
}
};
}])
.directive('owlCarouselItem', [function () {
return {
restrict: 'A',
transclude: false,
link: function (scope, element) {
if (scope.$last) {
scope.initCarousel();
}
}
};
}])