Angular ReferenceError: Controller is not defined - angularjs

I have a plunker here - http://plnkr.co/edit/ezKOtG9KJ6nD0068jpry?p=preview
I'm following this simple angular tutorial here - https://www.youtube.com/watch?v=aG8VD0KvUw4
When I run the code a get ReferenceError: Controller is not defined
Can anyone explain this or who to fix it.
var app = angular.module('myApp', []);
app.controller('ShieldCtrl', function($scope){
$scope.sheildNames = [];
this.addReigns = function(){
$scope.shieldNames.push('Reigns: One');
};
this.addCollins = function(){
$scope.shieldNames.push('Collins: Two');
};
this.addAmbrose = function(){
$scope.shieldNames.push('Ambrose: Three');
};
})
.directive('theshield', function(){
return{
restrict: 'E',
scope: {},
controller: 'ShieldCtrl',
link: function(scope, element, attrs){
element.bind('mouseenter', function(){
console.log(scope.sheildName);
})
}
}
})
.directive('reigns', function(){
return{
require: 'theshield',
link: function(scope, element, attrs, ShielCtrl){
ShieldCtrl.addReigns();
}
}
})
.directive('collins', function(){
return{
require: 'theshield',
link: function(scope, element, attrs, ShielCtrl){
ShieldCtrl.addCollins();
}
}
})
.directive('ambrose', function(){
return{
require: 'theshield',
link: function(scope, element, attrs, ShielCtrl){
ShieldCtrl.addAmbrose();
}
}
})

You have a simple spelling mistake, your directive controller dependencies are ShielCtrl and you're trying to use ShieldCtrl.
.directive('reigns', function(){
return{
require: 'theshield',
link: function(scope, element, attrs, ShielCtrl){
ShieldCtrl.addReigns(); <-- CHECK spelling.
}
}
})
Your next error is another spelling error: $scope.sheildNames = []; and you try to access the correct spelling: $scope.shieldNames.push('Reigns: One');

Related

Is there any ways to update directive link with scope or some other values?

I have dC directive
app.directive('dC', function($rootScope) {
return {
restrict: 'AE',
link: function(scope, element, attrs) {},
templateUrl: function(elem, attrs) {
return $rootScope.somePosiT
}
}
});
And I want to access inside of my controller as function is there anyway can I achieve it in order to change my directive location dynamically when click fired
app.controller('appCtrl', function($scope, $rootScope) {
clk: function() {
$rootScope.somePosiT = 'views/1.html'
}
})
I think you could do it using template and ng-include - rather than templateUrl. I think templateUrl is called before the scope values are available. You could try something like this:
app.directive('dC', function($rootScope) {
return {
restrict: 'AE',
link: function(scope, element, attrs) {},
template: '<div ng-include="somePosiT"></div>'
};
});
app.controller('appCtrl', function($scope, $rootScope) {
$scope.clk = {
somePosiT: "path/to/template.html"
};
});

Directive to directive communication using a service

I am attempting to perform the following. Use one directive to set information in a service.
Use another directive to retrieve information from this service. The directive setting the information seems to be doing it's job fine, however the one receiving the information does not react to it.
Below are how the directives look:
app.service('theStore',function(){
this.data;
});
app.directive('theOneThatSets', ['theStore', function(theStore){
return {
restrict: 'E',
link: function(scope, element, attrs) {
element.click(function(event){
theStore.data = attrs.val;
});
}
};
}]);
app.directive('theOneThatReads', ['theStore', function(theStore){
return {
restrict: 'E',
template: '<stong>Received Text is - {{receivedValue}}</strong>',
link: function(scope, element, attrs) {
scope.$watch('theStore.data',function(newVal){
scope.receivedValue = theStore.data;
});
}
};
}]);
plnkr here: http://plnkr.co/edit/9EMIwhUcneQoopNqqWtV
I don't know if you can do watchers on things that are not in scope. The best way to communicate between controllers/services/directives is to use $rootScope, $broadcast, and $on.
Example using your code:
app.directive('theOneThatSets', ['$rootScope', function(theStore){
return {
restrict: 'E',
link: function(scope, element, attrs) {
element.click(function(event){
//theStore.data = attrs.val;
$rootScope.$broadcast('changeThisValue', attrs.val); // Send
});
}
};
}]);
app.directive('theOneThatReads', [function(theStore){
return {
restrict: 'E',
template: '<stong>Received Text is - {{receivedValue}}</strong>',
link: function(scope, element, attrs) {
scope.$on('changeThisValue', function($event, value){
scope.receivedValue = theStore.data;
});
}
};
}]);
also, try creating a listener in your service like so:
app.service('myservice',function(){
this.listen = function($scope) {
$scope.$watch(function(){return someScopeValue},function(){
//$scope.dosomestuff();
});
}
});
//your controller
function myCtrl($scope,myservice) {
$scope.listen = function() {
myservice.listen($scope);
}
//call your method
$scope.listen();
}

Require one attribute between choices in directive

I am creating an angular directive and I want the user to specify a 'type' of the directive.
For example:
<my-directive type-a></my-directive>
or
<my-directive type-b></my-directive>
or
<my-directive type-c></my-directive>
I know I can do:
<my-directive type="a"></my-directive>
and then require the type attribute but then I'm doing string matching. Is there anyway to do this by requiring one of 'type-a', 'type-b', or 'type-c' to be present?
Without much background info, I came up with this solution.
JSFIDDLE
So basically myDirective has a controller which is shared by type directives (type-a, type-b.. and so on). The type directive sets the type on the scope of myDirective.
myApp.directive('myDirective', function() {
return {
restrict: 'E',
controller: function($scope) {
$scope.type = '';
this.setType = function(type){
if($scope.type === '') $scope.type = type;
else throw 'type can be only defined once. Current type is '+$scope.type
}
},
link: function(scope, elem, attrs) {
console.log(scope.type);
}
}
});
myApp.directive('typeA', function() {
return {
restrict: 'A',
require: '^myDirective',
link: function(scope, elem, attrs, ctrl) {
ctrl.setType('typeA');
}
}
});
myApp.directive('typeB', function() {
return {
restrict: 'A',
require: '^myDirective',
link: function(scope, elem, attrs, ctrl) {
ctrl.setType('typeB');
}
}
});
I think you can do <div data-my-directive="a"></div> which is a lot safer for cross-browser and w3c. Then the directive would be something like:
.directive('myDirective', function() {
return {
restrict: 'A',
scope: {
type: '='
},
link: function(scope,element,attrs){
}
};
});

AngularJS directive use required controller in controller

Say I have the following two directives that work with each other
directive('parent', function() {
return {
scope: {},
require: 'ngModel',
controller: function($scope) {
this.doSomething = function() {
//How to use ngModelController here?
};
},
link: function(scope, element, attr, ngModelController) {
}
};
});
directive('child', function() {
return {
scope: {},
require: '^parent',
link: function(scope, element, attr, parent) {
parent.doSomething();
}
};
});
How can I use the ngModelController from within the controller of parent? I suppose I could do scope.ngModelController = ngModelController inside the link function but that seems hacky. Is there a better solution?
Is this any less hacky?
directive('parent', function() {
var ngModelCtrl = null;
return {
scope: {},
require: 'ngModel',
controller: function($scope) {
this.doSomething = function() {
//How to use ngModelController here?
if (ngModelCtrl) {
}
};
},
link: function(scope, element, attr, ngModelController) {
ngModelCtrl = ngModelController;
}
};
});

How would I go about adding directives to an existing directive programmatically whilst ensuring that they have access to the same model?

I have attempted the following which seems to generate the correct html, but doesn't perform the data binding i.e. the new directives that I add do not have access to the $modelValue in ngController:
.controller('MyController', ['$scope', function($scope) {
$scope.aModel = {"key": "value"}
function init() {
$scope.aModel = {"key": "value"}
}
}])
.directive('innerDirective', [function (){
return {
restrict: 'AE',
require: 'ngModel',
template: '<ul></ul>',
link: function(scope, elem, attr, ngModelController) {
console.log(ngModelController.$modelValue) // Doesnt work
}
}
}])
.directive('outerDirective', ["$log", "$compile", function($log, $compile) {
return {
restrict: 'AE',
require: 'ngModel',
scope: {},
template: '<div></div>',
link: function(scope, elem, attrs, ngModelController) {
ngModelController.$render = function() {
var aModel = ngModelController.$modelValue; // Works
var modelName = attrs['ngModel']; // aModel
var html = '<inner-directive ng-model="' + modelName + '"></inner-directive>';
var angularElement = angular.element(html);
elem.append(angularElement);
$compile(angularElement)(scope);
}
}
};
}])
HTML looks like:
<div ng-controller="MyController">
<outer-directive ng-model="aModel"></outer-directive>
</div>
This is based on reccomendations from another question: Adding ngModel to input with a directive
What is it that I'm doing wrong here?
Cheers.
There is two issue:
1- outerDirective is using isolated scope. so aModel value is undefinded in the directive scope.
2-You can't access ngModelController.$modelValue in link function immediately. Look at outerDirective that you access it in the render function.
So you can change your directives as follows:
var app = angular.module('app', []);
app.controller('MyController', ['$scope', function ($scope) {
$scope.aModel = { "key": "value" }
function init() {
$scope.aModel = { "key": "value" }
}
}]);
app.directive('innerDirective', ['$timeout', function ($timeout) {
return {
restrict: 'AE',
require: 'ngModel',
template: '<ul></ul>',
link: function (scope, elem, attr, ngModelController) {
$timeout(function () {
console.log(ngModelController.$modelValue) // It works
});
}
}
}]);
app.directive('outerDirective', ["$log", "$compile", function ($log, $compile) {
return {
restrict: 'AE',
require: 'ngModel',
template: '<div></div>',
link: function (scope, elem, attrs, ngModelController) {
ngModelController.$render = function () {
var aModel = ngModelController.$modelValue; // Works
var modelName = attrs['ngModel']; // aModel
var html = '<inner-directive ng-model="' + modelName + '"></inner-directive>';
var angularElement = angular.element(html);
elem.append(angularElement);
$compile(angularElement)(scope);
}
}
};
}]);

Resources