I have a directive with an isolated scope and want to call its function to update data from the parent controller without using events.
var myApp = angular.module('MyApp',[]);
myApp.directive('myDirective', function() {
return {
scope: {},
link: function(scope) {
scope.update = function() {
alert('Directive updated!');
}
}
}
});
function MyCtrl($scope) {
$scope.updateDirective = function() {
// make me call update() function in directive
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="MyApp" ng-controller="MyCtrl">
<button ng-click="updateDirective()">Update!</button>
<span my-directive></span>
</div>
You could apply this solution.
In this way you are passing a variable in two way binding:
my-directive="myFunction" in the html
and myFunction: '=myDirective' in the directive)
Then assign the function in the directive:
scope.myFunction = function () {
alert('Directive updated!');
}
In this way you can use a function defined in a directive.
var myApp = angular.module('MyApp', []);
myApp.directive('myDirective', function () {
return {
scope: {
myFunction: '=myDirective'
},
link: function (scope) {
scope.myFunction = function () {
alert('Directive updated!');
}
}
}
});
function MyCtrl($scope) {
$scope.myFunction = {};
$scope.updateDirective = function () {
console.log( $scope.myFunction );
$scope.myFunction();
// make me call update() function in directive
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="MyApp" ng-controller="MyCtrl">
<button ng-click="updateDirective()">Update!</button> <span my-directive="myFunction"></span>
</div>
You could tackle this issue by introducing a new directive that is required by your isolated directive. Conveniently, you can assign the controller to this new directive.
Once required you then 'register' your isolated directive to the 'parent' directive as the target for your function. In the code snippet below I only provided a way to add 1 directive, but you could easily extend this to be an array of child directives. A good of example of such a setup are tabs, where each tab is a child directive of a common tabs directive.
angular.module("MyApp", []);
angular.module('MyApp').directive("myParentDirective", function(){
return {
controller: function ($scope) {
var childUpdate;
this.registerChild = function(_childUpdate_){
childUpdate = _childUpdate_;
};
$scope.updateDirective = function() {
childUpdate();
};
}
};
});
angular.module('MyApp').directive('myDirective', function() {
return {
require: '^myParentDirective',
scope: {},
link: function(scope, element, attrs, myParentController) {
myParentController.registerChild(update);
function update() {
alert('Directive updated!');
}
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="MyApp">
<div my-parent-directive>
<button ng-click="updateDirective()">Update!</button>
<span my-directive></span>
</div>
</div>
Related
I need to bind custom events in angularjs(1.x) and I tried with the following code,
HTML
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<link href="https://www.polymer-project.org/components/polymer/polymer.html" rel="import">
<link href="https://www.polymer-project.org/components/paper-button/paper-button.html" rel="import">
<div ng-app="demo-app">
<div ng-controller="DemoController">
<template bind-angular-scope is="auto-binding">
<paper-button raised on-tap="{{clickMe}}" on-mouseover="{{mouseOver}}">click me</paper-button>
</template>
<pre><code>{[{text}]}</code></pre>
</div>
</div>
Script
<script>
angular.module('demo-app', [])
.config(function ($interpolateProvider) {
$interpolateProvider.startSymbol('{[{').endSymbol('}]}');
})
.directive('bindAngularScope', function () {
return {
restrict: 'A',
link: function (scope, element, attrs) {
for (k in scope) {
if (!element[0][k]) {
element[0][k] = scope[k];
}
}
}
}
})
.controller('DemoController', function ($scope) {
$scope.text = '';
$scope.clickMe = function () {
$scope.text += '\nyou clicked me!!';
$scope.$apply();
};
$scope.mouseOver = function () {
$scope.text += '\nyou hovered me!!';
$scope.$apply();
}
});
</script>
This is not working.Could you point out me the issue or Is there is any solution for binding custom events(multiple) ? Do we need to create a custom directive for each of them ?
Note:
The above code is referred from the following url,
How to bind custom events in AngularJS?
Thanks in advance!
angular.module('demo-app', [])
.config(function ($interpolateProvider) {
$interpolateProvider.startSymbol('{[{').endSymbol('}]}');
})
.directive('bindAngularScope', function () {
return {
restrict: 'A',
link: function (scope, element, attrs) {
for (k in scope) {
if (!element[0][k]) {
element[0][k] = scope[k];
}
}
elem.bind('click', function() {
/* Place your click logic here * /
});
}
}
})
I have the following directive:
.directive("feedList", function() {
return {
restrict: 'E',
scope: {
feeds: '=feedData'
},
templateUrl: 'jstemplates/feed-list.html',
link: function(scope) {
angular.forEach(scope.feeds, function(value, key) {
if(value.who.fullname == " "){
scope.feeds[key].fullname = "email";
}
console.log(value.who.fullname);
});
}
}
})
Inside my template there is an event: ng-click="do()". How to handle this event in directive ot in parent controller?
As it's your isolated scope directive, so pass the callback function and then call that function directly from template or from controller or link function.
Working fiddle
var app = angular.module('myApp', []);
app.controller('AppCtrl', function($scope){
$scope.testFunction = function(){
alert("Called from isolated scope directive");
};
});
app.directive("isolatedScopeDirective", function(){
return{
scope:{
go:"&"
},
template : `<button ng-click='go()'>Test Button</button>`
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-controller="AppCtrl">
<isolated-scope-directive go="testFunction()"></isolated-scope-directive>
</div>
Is it possible to call a function on the controller when a ng-show sets to true and an previous hidden element is visible? I need a directive to run a function when the element it is inside goes from hidden to visible.
<div ng-show="showOrNot" >
This is secret text.
<my-directive> I need to call a function </my-directive>
</div>
You can use ng-init to call function and use ng-if here is example:
var app = angular.module('app',[]);
app.controller('Demo',['$scope', Demo]);
function Demo($scope){
$scope.showOrNot = false;
$scope.Show = function(){
$scope.showOrNot = true;
alert("shown");
}
$scope.hello = function(){
alert("function call!");
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div ng-app="app" ng-controller="Demo">
<div ng-if="showOrNot">
<div ng-init="hello()">This is secret text.</div>
</div>
<button ng-click="Show()">click</button>
</div>
You can simply pass the showOrNot scope to your directive's scope. Then $watch it and add the desired logic after the value changes.
Simply:
<my-directive value-to-watch="showOrNot">I need to call a function</my-directive>
Then the directive:
angular.module('app').directive('myDirective', function() {
return {
restrict:'E',
scope: {
valueToWatch:'='
},
controller: function($scope) {
$scope.$watch('valueToWatch', function (newValue, oldValue) {
//Case when new value is true and old value is false
if(newValue && !oldValue) {
//Call the function you want
}
});
}
}
})
you can use $watch in your controller inorder to call a function when it is true.
<my-directive content="showOrNot"> I need to call a function </my-directive>
.directive('myDirective', function() {
return {
restrict: 'E',
scope: {
content: '=',
}
link: function (scope, element) {
scope.$watch('content', function (newvalue, oldvalue) {
if(newvalue == true)
{
//your function here
}
});
}
}
}
you can write something like this.
I have this trigger / bind code:
service:
$('body').trigger('ready');
directive:
$('body').bind("ready", function(){
alert("Ready was triggered");
});
Can I do the exact same thing only using angular? If yes, how?
You need to use events in AngularJS check the below sample example I hope it will be of help to you, please check this article for more information on $emit, $on and $broadcast event system in AngularJS
angular
.module('demo', [])
.controller('DefaultController', DefaultController)
.factory('helloService', helloService)
.directive('hello', hello);
function DefaultController() {
var vm = this;
}
helloService.$inject = ['$rootScope'];
function helloService($rootScope) {
var service = {
sendHello: sendHello
};
return service;
function sendHello() {
$rootScope.$broadcast('helloEvent', 'Hello, World!');
}
}
hello.$inject = ['$rootScope', 'helloService'];
function hello($rootScope, helloService) {
var directive = {
restrict: 'E',
scope: {
message: '='
},
link: linkFunc
}
return directive;
function linkFunc(scope, element, attrs, ngModelCtrl) {
scope.$on('helloEvent', function (event, data) {
element.text(data);
});
sendHello();
function sendHello() {
helloService.sendHello();
}
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="demo">
<div ng-controller="DefaultController as ctrl">
<hello></hello>
</div>
</div>
If I use something like this in a directives link function:
var vdo = element.find('video')[0];
vdo.on('loadstart', function () {
console.log('onloadstart');
});
The code isn't executed. Instead I have to use:
vdo.onloadstart = function() {
console.log('onloadstart');
};
or
vdo.addEventListener('loadstart', function () {
console.log('onloadstart');
});
Can someone explain me why? And is it a problem to use addEventListener at all?
The angular way would be a custom directive:
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.src = 'w3schools.com/html/mov_bbb.mp4';
$scope.myFunc = function() {
alert('loadstart!');
};
}
myApp.directive('onLoad', function() {
return {
restrict: 'A',
scope: {
func: '&onLoad'
},
link: function(scope, element) {
element.on('loadstart', function() {
scope.func();
});
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl">
<video controls on-load="myFunc()">
<source ng-src="{{src}}">
</video>
</div>