passing object to angularjs directive from the controller - angularjs

Trying to get my head around AngularJS directives. I need to pass a full object from my main controller to the directive. See the code below and jsfiddle: http://jsfiddle.net/graphicsxp/Z5MBf/4/
<body ng-app="myApp">
<div ng-controller="MandatCtrl">
<div person myPerson="mandat.person"></div>
<span>{{mandat.rum}}</span>
<span>{{mandat.person.firstname}}</span>
</div>
and the script:
var myApp = angular.module("myApp", []);
myApp.controller("MandatCtrl", function ($scope) {
$scope.mandat = { rum: "15000", person: { id: 1408, firstname: "sam" } };
});
myApp.directive("person", function () {
return {
scope: {
myPerson: "="
},
template: 'test: <div ng-model="myPerson"><input type="text" ng-model="firstname" /></div>'
}
});
Ok, the binding is working fine for mandat.rum and mandat.person.firstname.
However, I'm trying to pass mandat.person to the directive, and it does not work. I know I must be doing something wrong, the question is what ? :)

Pls see below working copy
<!doctype html>
<html ng-app="plunker" >
<head>
<meta charset="utf-8">
<title>AngularJS Plunker</title>
<link rel="stylesheet" href="style.css">
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.min.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<span>{{mandat.rum}}</span>
<span>{{mandat.person.firstname}}</span>
<input type="text" ng-model="mandat.person.firstname" />
<my-directive mandateperson="mandat.person" >
</my-directive>
<script type="text/javascript">
var app = angular.module('plunker', []);
app.controller('MainCtrl', function ($scope) {
$scope.mandat = { name: "John", surname: "Doe", person: { id: 1408, firstname: "sam" } };
});
app.directive('myDirective', function () {
return {
restrict: 'E',
template: "<div><span>{{mandateperson.id}}<span><input type='text' ng-model='mandateperson.firstname' /></div>",
replace: true,
scope: { mandateperson: '=' }
}
}
)
</script>
</body>
</html>

Related

How to get value from a directive input field using angular

I am new to angular.js. I have two directives in my main.js file and every directive has an input text field in the template. There is a Html page (index.html) where I want to use these directive's text fields with another input text field which is a Html input text field.
Now I want whatever input user gives in both the directive's text fields the character count should be calculated and the sum should be printed in the third text field which is a Html text field.
Code is given below:-
Main.js file code :
/// <reference path="angular.min.js" />
var app = angular.module("myApp", []);
app.directive("textbox1", function() {
return {
restrict: 'E',
scope: {
timezone : "#"
},
template: "<div> <input type='text' style='background-color:orange; height=21px; width:151px;' ng-model='txtval1' ng-change='updateval()' />{{txtval1.length}} </div>"
}
});
app.directive("textbox2", function() {
return {
restrict: 'E',
scope: {
timezone: "#"
},
template: "<div> <input type='text' style='background-color:orange; height=21px; width:151px;' ng-model='txtval2' ng-change='updateval()'/>{{txtval2.length}} </div>"
}
});
app.controller("myCtrl", function ($scope) {
$scope.updateval = function () {
console.log($scope.txtval1.value);
$scope.txtThird = ($scope.txtval1.length) + ($scope.txtval2.length);
}
});
HTML Page Code :
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8" />
</head>
<body>
<div ng-app="myApp">
<textbox1></textbox1>
<textbox2></textbox2>
<br/><br/>
<input type="text" ng-model="txtThird"/>
</div>
<script src="scripts/angular.min.js"></script>
<script src="scripts/main.js"></script>
</body>
</html>
You need to do something like this:
var app = angular.module("myApp", []);
app.directive("textbox1", function() {
return {
restrict: 'E',
scope: {
timezone : "#",
updateval: "&updateval"
},
template: "<div> <input type='text' style='background-color:orange; height=21px; width:151px;' ng-model='txtval1' ng-change=\"updateval({inputNr:'1', textval: txtval1})\" />{{txtval1.length}} </div>",
}
});
app.directive("textbox2", function() {
return {
restrict: 'E',
scope: {
timezone: "#",
updateval: "&updateval"
},
template: "<div> <input type='text' style='background-color:orange; height=21px; width:151px;' ng-model='txtval2' ng-change=\"updateval({inputNr:'2', textval: txtval2})\" />{{txtval2.length}} </div>"
}
});
app.controller("myCtrl", function ($scope) {
$scope.inputValues = [
{
input: '1',
value: ''
},
{
input: '2',
value: ''
}
];
$scope.updateval = function (inputNr, txtval) {
var updatedInput = _.find($scope.inputValues, {input: inputNr});
updatedInput.value = txtval;
var lengthSum = 0;
angular.forEach($scope.inputValues, function(inputObj){
lengthSum += inputObj.value.length;
});
console.log(lengthSum);
}
});
Here is working: https://codepen.io/neptune01/pen/bWzLvq
Note that I used lodash.
If I understand you need something this:
//index.html
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8" />
</head>
<body ng-app="myApp">
<div ng-controller="myCtrl">
<textbox length="length1"></textbox>
<textbox length="length2"></textbox>
<br/><br/>
<input type="text" ng-model="txtThird"/>
<p>Sum = {{length1+length2}}</p>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<script src="script.js"></script>
</body>
</html>
//script.js
'use strict';
var app = angular.module("myApp", []);
app.directive("textbox", function() {
return {
restrict: 'E',
scope: {
length: '='
},
controller: function($scope){
},
template: "<div> <input type='text' style='background-color:orange; height=21px; width:151px;' ng-model='txtval' ng-change='length = txtval.length'/>{{txtval.length}} </div>"
}
});
app.controller("myCtrl", function ($scope) {
$scope.txtThird = "some text";
$scope.length1 = 0;
$scope.length2 = 0;
$scope.updateval = function () {
console.log($scope.txtval1.value);
$scope.txtThird = ($scope.txtval1.length) + ($scope.txtval2.length);
}
You can try it on plunker: https://plnkr.co/edit/XE6OcQX5GOJIPMcVHWum?p=preview

Components in Angular 1.5.8 and 1.6.1

Here is my very simple code:
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.js"></script> -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.min.js"></script>
</head>
<body>
<t-component test="test">
<div >
{{test}} John
</div>
</t-component>
<script>
angular.module('myApp', []).
component('tComponent', {
bindings: {
test: '='
},
controller: function() {
var self = this;
self.test='Hello';
}
});
</script>
</body>
</html>
I am getting Hello John only when using Angular 1.5.8. What do I have to do as to make the above to work with Angular 1.6.1? What am I missing?
I have this code working like that:
<t-component test="'test'"></t-component>
<script>
angular.module('myApp', []).
component('tComponent', {
template:'{{vm.test}} John',
bindings: {
test: '<'
},
controller: function() {
var self = this;
self.$onInit = function(){
// self.test ='hello'; //if you don`t want to use binding
}
},
controllerAs: 'vm'
});
</script>
<body>
<t-component test="'Hello'"></t-component>
<script>
angular.module('myApp', []).
component('tComponent', {
template: `
{{$ctrl.test}} John
`,
bindings: {
test: '='
},
controller: function() {
}
});
</script>
</body>
Then in controller you can change value of binding.
self.$onInit = function(){
self.test ='I am changed';
}

Which is the better way to provide API in AngularJS library

I am building a third-party library using AngularJS and I want to provide some API for user to interact with some internal properties/functions. Below are two solutions I'm considering, I want to know if some best practice for such a requirement.
Wrap the API in an scope object which can be accessed by the App.
angular.module('lib', []).directive('libDirective', function() {
return {
scope: {
api: '='
},
link: function(scope, elem, attrs) {
scope.api = {
sayHi: function() {
return 'Hi from lib';
}
};
}
};
});
angular.module('app', ['lib']).controller('AppCtrl', function($scope) {
// to do
});
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.5/angular.min.js"></script>
</head>
<body ng-app="app">
<div ng-controller="AppCtrl">
<lib-directive api="lib"></lib-directive>
{{lib.sayHi()}}
</div>
</body>
</html>
Wrap the API in a service which can be injected into the App module.
angular.module('lib', []).factory('libService', function() {
var hi = 'Hi from lib';
// return API
return {
sayHi: function() {
return hi;
}
};
});
angular.module('app', ['lib']).controller('AppCtrl', function($scope, libService) {
$scope.libHi = libService.sayHi();
});
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.5/angular.min.js"></script>
</head>
<body ng-app="app">
<div ng-controller="AppCtrl">
{{libHi}}
</div>
</body>
</html>

AngularJS : Adding attribute to directive element inside ng-repeat not working

I have a directive that works fine when used in isolation, but when it is used inside an ng-repeat it quits working. I know that ng-repeat creates it's own isolate scope, but that shouldn't matter since I'm not trying to do anything outside of the isolate scope of my directive. I've created a plunker to demonstrate the problem which you can see here: http://plnkr.co/edit/Y4ADmznnDCZvuxJrcZQ0?p=preview.
In the compile function of the directive I am adding an ng-click attribute to the element. Notice that the "This works" link (which is not in an ng-repeat) works fine but the other links (which are inside ng-repeat) do not work.
Here is the directive from the plunker:
var app = angular.module('plunker', []);
app.controller("AppCtrl", function($scope) {
$scope.users = [{
name: 'John',
id: 1
}, {
name: 'anonymous'
}];
});
app.directive("myDir", function($compile) {
return {
controller: 'directiveController',
compile: function(el) {
el.removeAttr('my-dir');
el.attr('ng-click', 'fxn()');
var fn = $compile(el);
return function(scope){
fn(scope);
};
}
};
})
.controller("directiveController", function($scope) {
$scope.fxn = function() {
alert('It works');
};
});
And here is the html:
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js#1.2.x" src="http://code.angularjs.org/1.2.12/angular.js" data-semver="1.2.12"></script>
<script src="app.js"></script>
</head>
<body>
<div>
<a my-dir>This works</a>
<a my-dir ng-repeat="id in [1,2]"><br>This does not work</a>
</div>
</div>
</body>
</html>
Try it with binding the event in the link function instead of adding another attribute that has to be compiled (DEMO):
app.directive("myDir", function($compile) {
return {
controller: 'directiveController',
compile: function(el) {
el.removeAttr('my-dir');
var fn = $compile(el);
return function(scope, el){
el.bind('click', scope.fxn);
fn(scope);
};
}
};
})

How to filter array if filter is in angular directive?

I try to create general directive for filtering array in angular.
<body ng-controller="MainCtrl">
controller: <input type="text" ng-model="query.name" /> - work<br>
directive: <span filter by="name"></span> - not work
<ul>
<li ng-repeat="item in list | filter:query">{{item.name}}</li>
</ul>
</body>
controller and directive are:
app.controller('MainCtrl', function($scope) {
$scope.list = [
{id: 1, name:'aaa'},
{id: 2, name:'bbb'},
{id: 3, name:'ccc'}
];
});
app.directive('filter', function () {
return {
scope: {
by: '#'
},
link: function postLink(scope, element, attrs) {
element.append(
'<input type="text" ng-model="query.' + attrs.by + '">');
}
}
});
Filter in controller works but filter in directive doesn't. I don't know how to fix it.
Solution is fixed in plunker: http://plnkr.co/edit/WLGd6RPQEwMFRBvWslpt?p=preview
Since you have isolated the scopes you have to use eiter $parent or you have to set up two way binding using '=' i have update your example with two way binding
<!doctype html>
<html ng-app="plunker" >
<head>
<meta charset="utf-8">
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
controller: <input type="text" ng-model="query.name" /> - work<br>
directive: <span filter by="query"></span> - not work
<ul>
<li ng-repeat="item in list | filter:query">{{item.name}}</li>
</ul>
<script>
var app = angular.module('plunker', []);
app.controller('MainCtrl', function ($scope) {
$scope.list = [
{ id: 1, name: 'aaa' },
{ id: 2, name: 'bbb' },
{ id: 3, name: 'ccc' }
];
alert("123");
$scope.query = { name: "" }
});
app.directive('filter', function () {
return {
scope: {
by: '='
},
replace: true,
template:'<input ng-model="by.name"></input>'
}
});
</script>
</body>
</html>

Resources