Customer Directive with Angular Material and controllerAs - javascript

I'm testing out Angular Material and I'm trying to use with a custom directive but it seems to not want to respect my binding of vm = this. Here's an example of what I'm trying.
HTML
<md-button ng-click="vm.test()">vm.Test</md-button>
JavaScript
(function() {
'use strict';
angular
.module('sidenav.directive', ['ngMaterial'])
.directive('sidenav', sidenav);
function sidenav() {
return {
templateUrl: 'app/components/sidenav/sidenav.directive.html',
restrict: 'EA',
controller: SidenavController,
controllerAs: 'vm',
bindToController: true
};
}
SidenavController.$inject = ['album', '$scope', 'authenticated', '$location', '$mdSidenav'];
function SidenavController(albumFactory, $scope, authenticated, $location, $mdSidenav) {
var vm = this;
vm.test = function () {
console.log('vm fired');
};
}
})();
The click event won't fire. However if I replace the vm in the controller with $scope and use just ng-click="test()" the button works. Any help on how to fix this would be appreciated.

Needed to add a scope to the directive, updated:
function sidenav() {
return {
templateUrl: 'app/components/sidenav/sidenav.directive.html',
restrict: 'EA',
controller: SidenavController,
controllerAs: 'vm',
bindToController: true,
scope: {
vm: '='
}
};
}

Related

AngularJS Custom directives - Issue accessing controllerAs variables/objects in directive link

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>

share data between sibling directives

Currently, I am facing one issue related to angularjs directive. I want to send outlet object from directive1 to directive2. Both directives having same controller scope. I tried with emitting event from directive1 to controller, broadcasting that event from controller to directive2 and listening to that event on directive2. but that is not working.
Directive1:
angular.module('moduleName')
.directive('directive1', function() {
return {
restrict: 'E',
templateUrl: 'directive1.html',
scope: false,
link: function(scope) {
scope.selectOutlet = function(outlet) {
scope.order.entityId = outlet.id;
scope.navigation.currentTab = 'right';
};
}
};
Here, in directive1, scope.selectOutlet() setting outletId to scope.order.entityId. I want to move/set that line to directive2 save function.
Directive2:
angular.module('moduleName')
.directive('directive2', function(config, $rootScope, $state) {
return {
restrict: 'E',
templateUrl: 'directive2.html',
scope: false,
link: function(scope) {
scope.save = function() {
// Save functionality
// scope.order.entityId = outlet.id; This is what i want to do
};
}
};
});
});
Any help.
you can use a factory or a service. Inject that factory into your directive. Now when you are trying set the data in function written into factory. `app.factory('shared',function(){
var obj ={};
obj.setData = function(){
// call this function from directive 1.
}
return obj;
})`
So if you include this factory into your directives you will get the data in 2 directives.
I will try to make some jsfiddle or plunker. If it is not clear.
Do the following in first directive
angular.module('moduleName')
.directive('directive1', function($rootScope) {
return {
restrict: 'E',
templateUrl: 'directive1.html',
scope: false,
link: function(scope) {
scope.selectOutlet = function(outlet) {
$rootScope.$broadcast('save:outlet',outlet);
//scope.order.entityId = outlet.id;
//scope.navigation.currentTab = 'right';
};
}
};
and in second
angular.module('moduleName')
.directive('directive2', function(config, $rootScope, $state) {
return {
restrict: 'E',
templateUrl: 'directive2.html',
scope: false,
link: function(scope) {
$rootScope.$on('save:outlet',function(event,data){
// do staff here
});
}
};
});

AngularJs ng-click not working directive

When I click on my HTML img, ng-click doesn't work. I don't understand why. This error happens in masonryPictureView.html
Main page - home.html
<ng-masonry>
<ng-picture ng-items="projectdescription.pictures"></ng-picture>
</ng-masonry>
Template of directive ngPicture - masonryPictureView.html
<ul class="grille">
<li ng-repeat="item in ngItems">
<img ng-click="test()" src="{{item.img}}"/> <------ NG-CLICK
</li>
</ul>
Directive in home.html
app.directive('ngMasonry', [function () {
return {
restrict: 'E',
scope: {},
transclude: true,
templateUrl: "shared/masonry/masonryView.html",
controller: function ($scope) {
xxxxxxxxx......
},
}
}])
app.directive('ngPicture', ['$modal', '$log', function ($modal, $log) {
return {
require: "^ngMasonry",
restrict: 'E',
scope: {
ngItems: '=ngItems'
},
templateUrl: "shared/masonry/masonryPictureView.html",
link: function (scope, element, attrs, ngMasonryCtrl) {
ngMasonryCtrl.setPictures(scope.ngItems);
},
controller: function ($scope) {
$scope.test = function () < -- -- - function call in NG - CLICK {
console.log("toto");
}
}
}
}])
Where does "projectdescription.pictures" come from?, Is it an array? Could it be empty?. Look in the console for errors. I recommend you that you use your namespace instead of ng for your custom directives or attributes. I made a plunker demostrating that anytime an image is clicked the test method is fired.
It is possible that you missed the ng-transclude placeholder on the ngMasonry directive?
template: '<div class="masonry"><ng-transclude></ng-transclude></div>',

error while passing data to directive in Angular

I have this simple directive:
angular.module('app')
.directive('ppBubble', function () {
function PpBubble($scope, $element, $attrs) {
var vm = this;
vm.message = $attrs.message;
vm.isSent = $attrs.sent;
}
return {
templateUrl: '../views/directives/ppBubble.html',
restrict: 'E',
controller: PpBubble,
controllerAs: 'vm',
bindToController: true
};
});
And here is how I use it:
<pp-bubble ng-repeat="msg in vm.messages" sent="{{msg.sent}}" message="{{msg.message}}"></pp-bubble>
The problem is that I see this "msg.message" instead of the string this object attribute hold:
Here is the messages array:
vm.messages = [
{
sent: true,
message: "aasdasd dsfsdfd"
}, ...
]
I am probably missing something stupid :(
The problem is that you're doing vm.message = $attrs.message; and you're taking the string literally, which means: {{msg.message}}, since that's the text that's written in that attribute:
message="{{msg.message}}".
You need to work with a scope to make Angular work its binding magic, and take the data from there:
function PpBubble($scope, $element, $attrs) {
var vm = this;
vm.message = $scope.message;
vm.isSent = $scope.sent;
}
return {
templateUrl: '../views/directives/ppBubble.html',
restrict: 'E',
scope: { message: "=", sent: "=" },
controller: PpBubble,
controllerAs: 'vm',
bindToController: true
};
Here is the messages array:
vm.messages = [
{
sent: true,
message: "aasdasd dsfsdfd"
}, ...
]
EDIT: Another thing is that now that you're binding from the directive, you need to bind to the variable itself, and not to its string literal, meaning to remove the {{}} from the directive HTML:
<pp-bubble ng-repeat="msg in messages" sent="msg.sent" message="msg.message"></pp-bubble>
Fiddle
Here is what worked for me:
function PpBubble($scope, $element, $attrs) {
var vm = this;
}
return {
templateUrl: '../views/directives/ppBubble.html',
restrict: 'E',
controller: PpBubble,
controllerAs: 'vm',
bindToController: true
};
});
Also i removed the {{}} from the html:
Thanks to #Omri Aharon

Use controller generated by typescript in angular directive

I have an angular controller (generated by typescript):
class FileManagerController {
...
constructor($scope) {
$scope.vm = this;
...
}
...functions...
}
How can I use this controller in the directive?
var myApp = angular.module('myApp', ])
.directive('ngFilemanager', function () {
return {
restrict: 'EA',
require: '^ngModel',
scope: {
ngModel: '='
},
templateUrl: '/templates/filemanager.html',
controller: ???
}
});
If the TypeScript class is not declared in a module, it would be as simple as:
....
controller: FileManagerController,
...
If you take a look at the Javascript compiled output of FileManagerController, you will find the function.

Categories