I created a custom directive in angular. I would like to pass parent data through the directive using scope but I'm getting 'undefined' when I log scope and scope.questionId.
HTML
<a class="waves-effect waves-light btn" my-directive="" on-flag="someFunction" question-id="question">Flag</a>
Angular Directive
angular.module('myApp').directive('myDirective', function($http) {
return {
restrict: 'A',
scope: {
onFlag: '&onFlag',
questionId: '='
},
link: function(scope, element, attrs) {
element.click(function() {
console.log(scope);
console.log(scope.questionId);
return;
});
}
};
});
Try this
elem.bind:- It uses the JQLite which is lite version of JQuery. Here we are writing the code to handle the click event performed on the directive.
It is same like JQuery $("class or id").click(). (I hope this explains is sufficient)
angular.module('myApp').directive('myDirective', function($http) {
return {
restrict: 'A',
scope: {
onFlag: '&onFlag',
questionId: '='
},
link: function(scope, elem, attrs) {
elem.bind('click', function() {
console.log(scope.questionId);
});
}
};
});
Related
I have a controller:
function myController($scope) {
$scope.clicked = false;
}
and a directive:
function myDirective() {
return {
restrict: 'E',
link: function(scope, elem, attrs) {
elem.bind('click', function() {
// need to update controller $scope.clicked value
});
},
template: '<div>click me</div>';
replace: true;
}
}
and I´m using it like this:
<div ng-controller="myController">
<my-directive></my-directive>
</div>
How can I change the controller value of $scope.clicked ?
thanks!
As you don't use isolated scope in your directive, you can use scope.$parent.clicked to access the parent scope property.
link: function(scope, elem, attrs) {
elem.bind('click', function() {
scope.$parent.clicked = ...
});
},
I would not recommend using scope.$parent to update or access the parent scope values, you can two way bind the controller variable that needs to be updated into your directive, so your directive becomes:
function myDirective() {
return {
restrict: 'E',
scope: {
clicked: '='
},
link: function(scope, elem, attrs) {
elem.bind('click', function() {
// need to update controller $scope.clicked value
$scope.clicked = !$scope.clicked;
});
},
template: '<div>click me</div>';
replace: true;
}
}
now pass this clicked from parent:
<div ng-controller="myController as parentVm">
<my-directive clicked="parentVm.clicked"></my-directive>
</div>
function myController() {
var parentVm = this;
parentVm.clicked = false;
}
I would recommend reading up on using controllerAs syntax for your controller as that would really solidify the concept of using two way binding here.
I like to use $scope.$emit for such purposes. It allows to send data from directive to the controller.
You should create custom listener in your controller:
$scope.$on('cliked-from-directive', function(event, data){
console.log(data)
})
As you can see, now you have full access to your controller scope and you can do whatever you want. And in your directive just to use scope.$emit
link: function(scope, elem, attrs) {
elem.bind('click', function() {
scope.$emit('cliked-from-directive', {a:10})
});
Here I've created jsfiddle for you
I'm having trouble with an angular directive. It doesn't seem to run the link function.
I feel like it's something obvious, but I just can't figure it out.
The directive is required as seen from below
angular.module('test').requires // ["injectedModule"]
Code below. Fiddle.
Any help would be amazing.
angular
.module('test', ['injectedModule'])
.controller('tester', [
function() {
this.test = function(data) {
alert(data);
}
}
]);
angular
.module('injectedModule', [])
.directive('testing', [
function() {
return {
restrict: 'E',
scope: true,
link: function(scope, element, attrs) {
alert(scope, element, attrs);
}
};
}
]);
<div ng-app="test">
<div ng-controller="tester as t">
<video id="test" ng-src="https://scontent.cdninstagram.com/hphotos-xfa1/t50.2886-16/11726387_1613973172221601_1804343601_n.mp4" testing="t.test(el)" />
</div>
</div>
Looks to me like
restrict: 'E',
should be
restrict: 'A',
Your directive isn't being called at all as it is.
I think the error is in the restriction you are giving to your directive.
You are restricting your directive to match only element (in other words tag). You should restrict to match attribute 'A'. Here's angular official documentation https://docs.angularjs.org/guide/directive
and here's your fiddle working
Code sample:
angular
.module('injectedModule', [])
.directive('testing', [
function() {
return {
restrict: 'A',
scope: true,
link: function(scope, element, attrs) {
alert(scope, element, attrs);
}
};
}
]);
I want to get a value straight from an attribute directive:
<form cronos-dataset="People as p">
Form Content
</form>
In my JS I tried:
app.directive('cronosDataset',[function() {
return {
restrict: 'A',
controller: 'CronosGenericDatasetController',
scope: {
"cronos-dataset" : '#'
}
};
}])
.controller("CronosGenericDatasetController",['$scope', function($scope) {
alert($scope["cronos-dataset"]);
}]);
I want to alert "People as p" string but I get undefined. Is that right path or should I go thorough a different approach?
You are supposed to have camelCase in the scope declaration
app.directive('cronosDataset',[function() {
return {
restrict: 'A',
controller: 'CronosGenericDatasetController',
scope: {
cronosDataset : '#'
}
};
}])
Here is a demo to see different variations
http://plnkr.co/edit/G6BiGgs4pzNqLW2sSMt7?p=preview
Make a link function instead:
app.directive('cronosDataset',[function() {
return {
scope: {},
restrict: 'A',
link: function (scope, elem, attrs) {
alert(attrs.cronosDataset);
}
Is there a way for not losing connection to the current controller when you are wrapping data with a directive ?
My problem is, that the directive within the wrapped template has no connection to the outside controller any more and so I can not execute the function.
Wrapping Directive:
myApp.directive('wrapContent', function() {
return {
restrict: "E",
scope: {
model: "=",
datas: "="
},
templateUrl: "./any/template.php",
link: function(scope, element, attr) {
// any
}
};
});
Directive within the wrapped Template
myApp.directive('doAction', function() {
return {
restrict: "A",
link: function(scope, elem, attrs) {
$(elem).click(function(e) {
scope.$apply(attrs.doAction);
});
}
}
});
Conroller:
lmsApp.controller('OutsideController', function ($scope){
$sope.sayHello = function() {
alert("hello");
};
});
HTML where I want to execute the function (template.php):
<div>
<do-action="sayHello()"></do-action>
</div>
How I call the wrapContent directive which is outside (Updated):
<div ng-controller="OutsideController">
<wrap-content model="any" datas="data_any"></wrap-content>
</div>
How can I execute the sayHello() function?
Thank you for your help! I would appreciate every answer.
wrapContent directive will be processed with the scope of controller.
DoAction directive will be processed with the isolateScope of wrapContent directive.
Solution1:
Get a reference to the sayHello function in wrapContent using '&' and execute it in event handler.
Solution2:
Instead of using scope in your event handler, use scope.$parent.
You should pass sayHallo function to your parent directive using &
myApp.directive('wrapContent', function() {
return {
restrict: "E",
scope: {
model: "=",
datas: "=",
sayHallo: "&"
},
templateUrl: "./any/template.php",
link: function(scope, element, attr) {
// any
}
};
});
HTML
<div ng-controller="OutsideController">
<wrap-content model="any" datas="data_any" sayHallo="sayHallo()"></wrap-content>
</div>
Then in your child directive, you will have sayHallo in your scope, to call it just do it this:
myApp.directive('doAction', function() {
return {
restrict: "A",
link: function(scope, elem, attrs) {
scope.sayHallo();
}
}
});
And you dont need pass it again. So your child directive should looks like this:
<div>
<do-action></do-action>
</div>
UPDATE
If you want to use all your parent model functions,without passing each function. In your child directive,just use scope.model to have access to model attributes and functions.
myApp.directive('doAction', function() {
return {
restrict: "A",
link: function(scope, elem, attrs) {
scope.model.sayHallo();
}
}
});
So I know that I can have the model be different than the view value by using $parsers.
But what if I want to have the model change, without using $parsers?
For example:
html
<input tel-input ng-model="data.phone">
{{data.phone}}
js
.directive('telInput', function($compile) {
return {
restrict: 'A',
scope: {
ngModel: '='
},
link: function(scope, elem, attrs) {
elem.on('paste', function() {
scope.ngModel = 'special model value after pasting';
});
}
};
});
The problem with this is that when scope.ngModel = 'pasting not allowed occurs, it changes the value in the input.
With $parsers, it changes the value in the model, but the view value remains the same.
There isn't any $setModelValue method, which seems like it would serve this purpose.
Any ideas?
Try this,
.directive('telInput', function() {
return {
restrict: 'A',
require: 'ngModel',
link: function(scope, elem, attrs, ngModel) {
elem.on('paste', function() {
ngModel.$setViewValue('special model value after pasting');
ngModel.$render();
});
}
};
});