I have an issue with my directive after migration to lastest angular.
.directive('documentGrid',
function() {
return{
restrict: 'EA',
scope: {
documentData: '=',
remove: '&',
edit: '&',
documentDatasources: '='
},
controller: 'DocumentCrtl',
controllerAs: 'vmDocument',
//bindToController: true,
//transclude: true,
templateUrl: '/Custom/Document/document.cshtml'
};
});
<div class="box" document-grid document-data="widget"
document-datasources="vm.datasource.data"
remove="vm.remove(item)"
edit="vm.openSettings(item,datasources)">
</div>
before move to lastest version it works fine with bind controller set to true but now it does't work. So I remove the bindToController : true and I need to use $scope to access to my varibile bind from html directive
I read guide, post and tutorial about directive but I don't find any solution.
Try to replace with this:
directive('documentGrid',
function() {
return{
restrict: 'EA',
bindToController: {
documentData: '=',
remove: '&',
edit: '&',
documentDatasources: '='
},
controller: 'DocumentCrtl',
controllerAs: 'vmDocument',
scope: {},
//transclude: true,
templateUrl: '/Custom/Document/document.cshtml'
};
});
Note that I changed bindToController and scope.
Then in your controller your must bind this, e.g.: var vm = this; at the first line of your controller preferably.
Finally you will be able to access your data in controller like this:
vm.documentData
See this fiddle: https://jsfiddle.net/2n5skwqj/794/
In the controller function I log the name.
Related
I've just started refactoring my code to do DOM manipulation and functions in directives instead of inside controllers as I had previously been doing, but I'm having issues accessing variables/objects defined using controllerAs 'this' syntax within the controller from which I need them to be inherited.
I've tried using bindToController as below, where I've added the different objects that are used in the directive function, but when I try to access these withink the 'link', they're all returning as undefined in the console.
Example here. 'this.test' defined in controller, tried accessing this in the directive in a console log message.
Controller:
app.controller('notificationsController', function($scope, $state, $http, $document, $mdDialog, $filter, $timeout, $mdToast) {
this.test = 'TEST';
Directive:
app.directive('clearNotifications', function($mdDialog, $mdToast, $timeout) {
return {
controller: 'notificationsController',
controllerAs: 'notifications',
scope: {},
bindToController: {
notifications: '=',
filters: '=',
test: '#'
},
restrict: 'A',
link: function(scope, element, attrs) {
element.bind('click', function() {
console.log('notifications.test string test: ' + notifications.test);
this in controller is different with controllerAs in directive , in directive you should use ctrl or model to binding.
var app = angular.module("app", []);
app.controller("notificationsController", function($scope) {
this.test = "foo!";
})
app.directive("clearNotifications", function() {
return {
controller: 'notificationsController',
controllerAs: 'notifications',
scope: {},
bindToController: {
notifications: '=',
filters: '=',
test: '#'
},
restrict: 'A',
link: function(scope, element, attrs, ctrl) {
element.bind('click', function() {
console.log('notifications.test string test: ' + ctrl.test);
})
}
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<button clear-notifications>clearNotifications</button>
</div>
I need to get append directive attribute value to templateUrl.
I tried several options however, templateUrl does not support $observe in it.
Therefore I tried below and tried to get "devicePath" value to templateUrl.
Nothing worked.
Here is my example.
<me-direct device-path="{{contentUrl}}" tmp-url="{{appTemplateUrl}}"></me-direct>
Directive js file
angular.module('meDevices').directive('medirect',medirect);
function medirect(){
return{
scope:{
devicePath:'#'
},
restrict: 'E',
controller: 'directCtrl',
link: function(scope, element, attrs) {
// some ode
attrs.$observe('devicePath', function(value){
console.log(value);
scope.url = value;
console.log(scope.url);
});
},
templateUrl: scope.url
}
}
Anyhow, this is not working since scope.url is not accessible from templateUrl. Any thoughts??
EDIT
But If I send attribute as this everything will work.
<me-direct device-path="some/common/url/to/view.html" tmp-url="{{appTemplateUrl}}"></me-direct>
Try this:::
angular.module('meDevices').directive('medirect',medirect);
function medirect(){
return{
restrict: 'E',
scope: {
base: '#baseUrl'
},
templateUrl: function(element, attrs) {
return "http://example.com/"+attrs['device-path']+attrs['tmp-url'];
}
}
}
Uses:
<me-direct device-path="{{contentUrl}}" tmp-url="{{appTemplateUrl}}"></me-direct>
I got a problem by passing a function to a directive ( familiar to this post: AngularJS - pass function to directive but i can´t get it working)
Here is my Code:
Directive:
.directive('testdirective', function(){
return{
restrict: 'E',
scope: {
onClick: '&'
},
controller: 'TestController',
controllerAs: 'tc',
bindToController: true,
template: '<div><button ng-click="onClick()">What UP</button></div>',
replace: true
}
})
Controller:
TestController.$inject = ["$scope"];
function TestController($scope) {
$scope.testFunction = function(){
alert("I´m the alert of the TestContoller");
};
$scope.test = 'test';
}
HTML:
<div>
<testdirective on-click="testFunction()"></testdirective>
</div>
What I want sounds very simple, I just want to pass the function to the directive and execute it with the ng-click on the button.
For me my code looks exactly like this fiddle
but mine is not working :/
Would be awesome if someone got some hints for me.
EDIT
My directive will need his own controller !
Later the function to be passed in will come from another controller !!!
The fiddle is not the same as your code.
You have set the controller of your directive to be "TestController". I assume what you wanted to do was:
.directive('testdirective', function(){
return{
restrict: 'E',
scope: {
onClick: '&'
},
template: '<div><button ng-click="onClick()">What UP</button></div>',
replace: true
}
});
and in your HTML,
<div ng-controller="TestController">
<testdirective on-click="testFunction()"></testdirective>
</div>
EDIT: Based on OP's comment
app.directive('testdirective', function(){
return{
restrict: 'E',
scope: {
onClick: '&'
},
template: '<div><button ng-click="tc.onClick()">What UP</button></div>',
replace: true,
controller: 'TestController',
controllerAs: 'tc',
bindToController: true
}
});
app.controller('TestController', function ($scope) {
console.log($scope);
}) ;
app.controller('AnotherController', function ($scope) {
$scope.testFunction = function(){
alert("I´m the alert of the TestContoller");
};
$scope.test = 'test';
});
And, your HTML
<div ng-controller="AnotherController">
<testdirective on-click="testFunction()"></testdirective>
</div>
You are telling the directive to bindToController. So within the directive's template, onClick is bound to the controller and not the scope. So, you access the onclick via the controller as tc.onClick() in the directive's template.
You may want to pass a method as a reference:
1.Pass the function as a reference and not a call:
<div>
<testdirective on-click="testFunction"></testdirective>
</div>
2.Update the directive:
.directive('testdirective', function(){
return{
restrict: 'E',
scope: {
onClick: '='
},
template: '<div><button ng-click="onClick()">What UP</button></div>',
replace: true
}
});
JSFIDDLE.
Well, in your testdirective,you defined controller TestController.
The testFunction() that you try to calling via onClick directive scope parameter is defined in controller TestController which is directive controller.
So, rather than calling via onClick you can call directly like
template: '<div><button ng-click="testFunction()">What UP</button></div>'.
Its very confusing ,you defining controller in directive and again referring it's one function via same directive's scope parameter which look like recursive.
If you want to call via directive scope parameter then you should do belowe changes.
for e.g.
JS :
<div ng-controller="TestController" ng-app="dr">
<testdirective on-click="testFunction()"></testdirective>
</div>
app.directive('testdirective', function() {
return{
restrict: 'E',
scope: {
onClick: '&'
},
template: '<div><button ng-click="onClick()">What UP</button></div>',
replace: true
}
});
Directivie:
.directive('testdirective', function(){
return{
restrict: 'E',
scope: {
onClick: '=onClick'
},
controller: 'TestController',
controllerAs: 'tc',
bindToController: true,
template: '<div><button ng-click="onClick()">What UP</button></div>',
replace: true
}
})
use '=' instead of '&' so you can fetch the html function in your directive. and you can simply pass onClick parameter through HTML
HTML:
<div>
<testdirective on-click="testFunction()"></testdirective>
</div>
I have 2 directives, one for searching and one for pagination. The pagination directive needs to access the search directive to find out what property we're currently searching by. When I load the page though, it throws an error saying Error: [$compile:ctreq] Controller 'search', required by directive 'pagination', can't be found!. However I have a controller setup in my search directive.
Here is my search directive:
angular.module('webappApp')
.directive('search', function ($route) {
return {
templateUrl: 'views/search.html',
restrict: 'E',
scope: {
searchOptions: '=',
action: '=',
currentProperty: '=',
currentValue: '='
},
controller: function($scope) {
$scope.searchBy = $scope.searchOptions[0].text;
$scope.searchByProperty = $scope.searchOptions[0].property;
$scope.setSearchBy = function(event, property, text) {
event.preventDefault();
$scope.searchBy = text;
$scope.searchByProperty = property;
};
$scope.search = function() {
$scope.searching = true;
$scope.currentProperty = $scope.searchByProperty;
$scope.currentValue = angular.element('#searchCriteria').val();
$scope.action($scope.searchByProperty, $scope.currentValue, function() {
$scope.searching = false;
});
};
$scope.reload = function() {
$route.reload();
};
}
};
});
Here is my pagination directive:
angular.module('webappApp')
.directive('pagination', function () {
return {
templateUrl: 'views/pagination.html',
restrict: 'E',
require: '^search',
scope: {
basePath: '#',
page: '=',
sort: '='
},
link: function(scope, element, attrs, searchCtrl) {
console.debug(searchCtrl);
scope.searchByProperty = searchCtrl.searchByProperty;
}
};
});
In order for one directive to use another's controller by use of require, it needs to either share the same element as the controller containing directive, or it has to be a child of it.
You can't use require in the way you have, where the elements are siblings.
Angular docs about directives, including require
If it doesn't make sense to rearrange the DOM in the way I've described, you should inject a service into both directives which contains the data/methods you wish to share between the two.
Note: you could also experiment with the $$nextSibling / $$prevSibling properties of the directives' scopes, but this would present only a very fragile solution
You cannot use require in directive like that, however , since the only thing you need to pass between directives is a string , just bind them to the same property in parent controller (it can be parent directive controller):
...
<div ng-app='app' ng-controller='MyCtrl as ctrl'>
<my-dir-one s1='ctrl.message'></my-dir-one>
<my-dir-two s2='ctrl.message'></my-dir-two>
and first directives:
app.directive('myDirOne', function ($route) {
return {
templateUrl: 'views/my-dir-one.html',
restrict: 'E',
scope: {
s1: '=',
second directive
app.directive('myDirTwo', function ($route) {
return {
templateUrl: 'views/my-dir-one.html',
restrict: 'E',
scope: {
s2: '=',
Updating as there is some confusion as to what I am asking. I would like to use a directive to inject a variable into the controller used by that directive. I realize I can use the $scope for that, but I don't find that an intuitive solution.
Essentially I want my controller to have the proposal variable injected into it.
My intended usage:
<blah-directive proposal="proposal"></blah-directive>
The directive (so far):
app.directive('blahDirective', function () {
return {
restrict: 'E'
, transclude: true
, replace: true
, scope: {
proposal: '='
}
, templateUrl: 'blahTemp.html'
, controller: blahController
};
});
blahTemp.html
<form class="form-horizontal" role="form" name="myBidForm">
**{{ proposal }}**
</form>
this is displaying the value proposal variable in the $scope fine, but it is not what I want. Essentially I would like to define my controller like:
var blahController = function($scope, SomeOtherResource, proposal) {
}
If you want to inject locals into a controller use $controller.
Here is an example (plunker):
app.directive('blahDirective', function ($controller) {
return {
restrict: 'E',
scope: {
proposal : "="
},
transclude: true,
replace: true,
templateUrl: 'blahTemp.html',
link : function (scope, elm, attrs){
scope.proposal = {};
var locals = {
$scope: scope ,
proposal: scope.proposal
};
$controller('blahController', locals);
}
};
});