Why is change in service not updating the controller? - javascript

Can someone explain why my code is not working as expected?
I expect after clicking the button, the text should be updated. But apparently, it is not the case.
I really appreciate any help.
main.js
x = angular.module('app', []);
x.directive("changer", function(myService){
return {
restrict: "E",
template: "<button>click</button>",
replace: true,
link: function (scope, elem, attrs) {
elem.click(function () {
myService.item1 = 'updated';
scope.$apply();
})
}
}
});
x.service('myService', function () {
var item = {'item1': 1, 'item2': 2};
return {
item : item,
};
});
x.controller('myController', function ($scope, myService) {
$scope.item = myService.item;
});
main.html
<!DOCTYPE html>
<html ng-app="app">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script src="main.js"></script>
</head>
<body ng-controller='myController'>
<changer></changer>
{{item.item1}}
</body>
</html>
Thanks!

It is easier and better use 'ng-click' inside your directive template please see demo below
x = angular.module('app', []);
x.directive("changer", function(myService) {
return {
restrict: "E",
template: "<button ng-click='update()'>click</button>",
replace: true,
link: function(scope, elem, attrs) {
scope.update = function() {
myService.item.item1 = 'updated';
}
}
}
});
x.service('myService', function() {
var item = {
'item1': 1,
'item2': 2
};
return {
item: item,
};
});
x.controller('myController', function($scope, myService) {
$scope.item = myService.item;
$scope.test = "dfsf"
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body>
<div ng-app="app">
<div ng-controller='myController'>
<pre>{{item| json}}</pre>
<changer></changer>
</div>
</div>
</body>

Related

Angularjs limit to directive

I'm trying to make a filter be used as a directive in Angularjs 1.4
What I want to make is to limit string using limitTo filter but as a directive not (|) filter.
I made this but it's not working
charlimit.js directive
function controller($scope) {
$scope.length = 15;
}
angular.module('xApp')
.directive('charlimit', function () {
return {
restrict: 'A',
scope: {
limitTo: '#',
},
controller: ["$scope", controller]
};
});
index.html
<p charlimit="5"></p>
Do you have any thoughts?
Thanks.
var app = angular.module("xApp", []);
app.directive('charLimit', function() {
return {
restrict: "A",
link: function(scope, element, attrs) {
var limitLength = parseInt(attrs.charLimit);
scope.limittext = scope.limittext.substring(0, limitLength);
return scope.limittext;
}
}
});
app.controller("IndexController", function($scope) {
$scope.limittext = 'Sample text';
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="xApp" ng-controller="IndexController">
<p char-limit="5">{{limittext}}</p>
</body>

Where to define a local function in a AngularJS Directive

Where do I have to define my function button() in the directive, such that pressing the button will trigger the function?
I don't want to use the outer scope of the app, I just want to use the local scope.
var app = angular.module("myApp", []);
app.directive('aaaa', function() {
return {
restrict: 'E',
scope: {
data: '=',
//this is not working: button: function(){console.log('hello from button');}
},
link: function(scope, element) {
element.append('hello');
element.append(' <button type="button" ng-click="button()">Click Me!</button> ')
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div ng-app="myApp">
<aaaa></aaaa>
</div>
As #tymeJV said , you need to compile the html first and then call button() in directive controller
var app = angular.module("myApp", []);
app.directive('aaaa', function($compile) {
return {
restrict: 'E',
scope: {
data: '=',
//this is not working: button: function(){console.log('hello from button');}
},
link: function(scope, element) {
element.append('hello');
var htmlText = ' <button type="button" ng-click="button()">Click Me!</button> ';
var template = angular.element($compile(htmlText)(scope));
element.append(template);
},
controller: function($scope, $element){
$scope.button = function(){
console.log('button clicked');
}
}
}
});
I would advise to use angular templates instead of element.append, see example code below. Then you don't need all the compiler code 'n stuff.
You could also replace "template: 'hello
var app = angular.module("myApp", []);
app.directive('aaaa', function() {
return {
restrict: 'E',
scope: {
data: '='
},
link: function(scope, element) {
scope.button = function(){
console.log('hello from button');
};
},
template: 'hello <button type="button" ng-click="button()">Click Me!</button>'
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div ng-app="myApp">
<aaaa></aaaa>
</div>
you can out under link
link: function(scope, element) {
element.append('hello');
element.append(' <button type="button" ng-click="button()">Click Me!</button> ');
scope.button=function(){
//content goes here
}
}

How to use angular listener when using ng-repeat?

When I click a button, the controller will get data from some $http service callback function and will $broadcast it on $scope. Then, in the directive, I have a listener to get the data and do some logic. But, when I am using ng-repeat on button for several formats, the listener will get fired for all ng-repeat items when I click on each button. How can I make the listener to get fired only for the clicked button? Please see the sample code below.
var app = angular.module('demoApp', []);
app.controller('MyCtrl', function($scope) {
var myCtrl = this;
myCtrl.getFile = function(){
var response = 'some data';
$scope.$broadcast('downloadFile', {'response': response});
}
});
app.directive('fileDownload', function(){
return {
restrict: 'A',
link: function(scope, elem, attrs){
var cancelEvent = scope.$on('downloadFile', function(event, args){
console.log('called', args);
});
scope.$on('$destroy', function(){
cancelEvent();
});
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="demoApp">
<div ng-controller="MyCtrl as myCtrl">
<button ng-repeat="format in ['TXT','PDF','CSV']" ng-click="myCtrl.getFile()" file-download>{{ format }}</button>
</div>
</div>
In this sample you can figure out how can create directive using scope, i create a sample to get all formats get all lists, get checked list, get download format, on directive.
About your codes, actually response is true, because when we use some functions like [$broadcast] or ... on app run all data already sets in our scopes. but remember in this case you don't need to use $broadcast that because our actions are in-time and we can get them when we click on a function.
hope helps you my friend
var app = angular.module('app', []);
app.controller('ctrl', function ($scope) {
var self = this;
self.lists = [
{ name: "A"},
{ name: "B"},
{ name: "C"},
{ name: "D"}
];
self.getFile = function () {
console.log('controller', "done");
}
});
app.directive('fileDownload', function ($filter) {
return {
restrict: 'A',
scope: {
fileDownload: "=",
list: "="
},
link: function (scope, elem) {
elem.on("click", function () {
var filter = $filter("filter")(scope.list, { checked: true });
console.log('from directive, all list', scope.list);
console.log('from directive, checked list', filter);
console.log('from directive, download format', scope.fileDownload);
});
}
}
});
<!DOCTYPE html>
<html ng-app="app" ng-controller="ctrl as self">
<head>
<title></title>
</head>
<body>
<small>list</small>
<ul>
<li ng-repeat="list in self.lists">
<input type="checkbox" ng-model="list.checked"/>
{{list.name}}
</li>
</ul>
<small>download format</small>
<button ng-repeat="format in ['TXT','PDF','CSV']" ng-click="self.getFile()" list="self.lists" file-download="format">{{ format }}</button>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
</body>
</html>
I think it will help you
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="demoApp">
<div ng-controller="MyCtrl as myCtrl">
<span ng-repeat="format in ['TXT','PDF','CSV']">
<span get-file="myCtrl.getFile({data: data})" file-download title="format"></span>
</span>
</div>
</div>
</body>
<script type="text/javascript">
var app = angular.module('demoApp', []);
app.controller('MyCtrl', function($scope) {
var myCtrl = this;
myCtrl.getFile = function(data) {
var response = 'some data';
console.log(response);
console.log(data);
// $scope.$broadcast('downloadFile', {'response': response});
}
});
app.directive('fileDownload', function() {
return {
restrict: 'A',
template: "<button ng-click='callFn()'>{{title}}</button>",
scope: {
title: '=',
getFile: '&'
},
link: function(scope, elem, attrs, ctrl) {
scope.callFn = function(){
scope.getFile({data: scope.title});
}
// var cancelEvent = scope.$on('downloadFile', function(event, args) {
// console.log('called', args);
// });
// scope.$on('$destroy', function() {
// cancelEvent();
// });
}
}
});
</script>
</html>

Angular.js ng-repeat callback

I need to send a callback when ng-repeat finishes, but my solutions don't work. In my last solution I used a directive to do it.
Markup:
<div class="results" ng-model="results">
<div class="empl-card" ng-repeat="empl in employees | filter: searchQuery" callback-on-end="alert('callback')">
...
</div>
</div>
directive:
app.directive("callbackOnEnd", function() {
return {
restrict: "A",
link: function(scope, element, attrs) {
if (scope.$last) {
scope.$eval(attrs.callbackOnEnd);
}
}
};
});
Where could I have made a mistake?
I think you can do this with just ngInit as follows;
<div class="results" ng-model="results">
<div class="empl-card" ng-repeat="empl in employees | filter: searchQuery" ng-init="$last && alert('callback')">
...
</div>
</div>
You don't need a custom directive for doing this.
To achieve this you need to make a method in your controller and call that method when the ng-repeat ends :
(function() {
angular.element(document).ready(function() {
var app = angular.module('myApp', []);
app.controller("MyCtrl", function($scope, $timeout) {
$scope.names = ['A', 'B', 'C', 'D'];
$scope.onEnd = function() {
alert('all done');
};
});
app.directive("callbackOnEnd", function() {
return {
restrict: "A",
link: function(scope, element, attrs) {
if (scope.$last) {
scope.$eval(attrs.callbackOnEnd);
}
}
};
});
angular.bootstrap(document, ['myApp']);
});
}());
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-controller="MyCtrl" class="well">
<h3 ng-repeat="name in names" callback-on-end="onEnd()">{{name}}</h3>
</div>
Or you will have to eval the javascript code
app.directive("callbackOnEnd", function() {
return {
restrict: "A",
link: function(scope, element, attrs) {
if (scope.$last) {
eval(attrs.callbackOnEnd);
}
}
};
});
(function() {
angular.element(document).ready(function() {
var app = angular.module('myApp', []);
app.controller("MyCtrl", function($scope, $timeout) {
$scope.names = ['A', 'B', 'C', 'D'];
$scope.onEnd = function() {
alert('all done');
};
});
app.directive("callbackOnEnd", function() {
return {
restrict: "A",
link: function(scope, element, attrs) {
if (scope.$last) {
eval(attrs.callbackOnEnd);
}
}
};
});
angular.bootstrap(document, ['myApp']);
});
}());
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-controller="MyCtrl" class="well">
<h3 ng-repeat="name in names" callback-on-end="alert('done')">{{name}}</h3>
</div>
Find good explanation here :
https://stackoverflow.com/a/15671573/3603806
Check here. Created custom directive for repeatEnd
http://plnkr.co/edit/YhGzYFOcVaVds7iAEWPn?p=preview
<h3 ng-repeat="name in names" repeat-end="onEnd()">{{name}}</h3>
app.js
angular.element(document).ready(function() {
var app = angular.module('repApp', []);
app.controller("MainCtrl", function($scope, $timeout) {
$scope.names = ['user1', 'user2', 'user3'];
$scope.onEnd = function() {
$timeout(function() {
alert('all done');
}, 1);
};
});
app.directive("repeatEnd", function() {
return {
restrict: "A",
link: function(scope, element, attrs) {
if (scope.$last) {
scope.$eval(attrs.repeatEnd);
}
}
};
});
angular.bootstrap(document, ['repApp']);
});

i cant update variable via directive in angularjs

i want to make my variable true to false in directive..
the problem is that my directive console correct but in view can't be changed .
here is Plunker Link...
var app = angular.module('my-app', [], function () {
})
app.controller('AppController', function ($scope) {
$scope.test=true;
$scope.items = ["One", 'Two'];
})
app.directive('myDir', function () {
return {
restrict: 'E',
scope: {
myindex: '=',
myTest:'='
},
template:'<div>{{myindex}}</div>',
link: function(scope, element, attrs){
console.log('test', scope.myindex);
element.click(function(){
scope.myTest=false;
console.log(scope.myTest);
});
}
};
})
Pls check it out
var jimApp = angular.module("mainApp", []);
jimApp.controller('mainCtrl', function($scope){
$scope.test = true;
$scope.items = ["One", 'Two'];
})
.directive("myDir", function() {
return {
restrict : "E",
scope:{ myindex: '=', myTest:'=' },
template : "<div >Jimbroo{{myindex}} {{myTest}}</div>",
link: function(scope, element, attrs){
element.bind('click', function() {
scope.myTest = false;
scope.$apply();
});
}
};
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular.min.js"></script>
<div ng-app="mainApp" ng-controller="mainCtrl">
<div ng-repeat="item in items">
{{test}}
<my-dir myindex="$index" my-test="test" ></my-dir>
</div>
</div>
here is code updated
1 - use updated version of angularjs
2 - Use # in directive
var app = angular.module('my-app', [], function () {
})
app.controller('AppController', function ($scope) {
$scope.test=true;
$scope.items = ["One", 'Two'];
})
app.directive('myDir', function () {
return {
restrict: 'E',
scope: {
myindex: '#',
myTest:'#'
},
template:'<div>{{myindex}}</div>',
link: function(scope, element, attrs){
console.log('test', scope.myindex);
element.click(function(){
scope.myTest=false;
console.log(scope.myTest);
});
}
};
})
<!DOCTYPE html>
<html ng-app="my-app">
<head lang="en">
<meta charset="utf-8">
<title>Custom Plunker</title>
<link rel="stylesheet" href="style.css">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.min.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="AppController">
<div ng-repeat="item in items track by $index">{{test}}
<my-dir my-test="test" myindex='{{$index}}'></my-dir>
</div>
</body>
</html>
use scope.$apply to know your scope changes in angular
plnkr
var app = angular.module('my-app', [], function () {
})
app.controller('AppController', function ($scope) {
$scope.test=true;
$scope.items = ["One", 'Two'];
})
app.directive('myDir', function () {
return {
restrict: 'E',
replace: true,
scope: {
myindex: '#',
myTest:'#'
},
template:'<div>{{myTest}}</div>',
link: function(scope, element, attrs){
element.click(function(){
scope.$apply(function() {
scope.myTest=false;
console.log('called');
})
});
}
};
})

Categories