angular directive not working - javascript

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

How to use custom directive on Input fields in Angular 1.x?

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>"
}
});

interpolating an attribute value in an Angular template causes a parse error

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>

Bind dynamic loaded content to Angular

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>

Can't update $scope value in directive

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>

how to make directive in angular of owl carousel?

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();
}
}
};
}])

Categories