Angular JS - Sharing controller between directives - javascript

Can't seem to figure out why this is not working...
What I'm trying to do:
I need to be able to share the controller from the mainContent directive with the directive for focus and I keep getting this error: Cannot set property 'element' of undefined.
I'm practically copying/pasting from this example : https://www.codeschool.com/screencasts/egghead-io-flexible-angular-directives : so I'm not sure why it isn't working?
Relevant Code:
//html
<mainContent id="mainContent">
<focus>whatever</focus>
</mainContent>
//js
angular.module('home', [])
.directive('mainContent', mainContent)
.directive('focus', focus);
mainContent.$inject = [];
function mainContent() {
return {
restrict: 'E',
scope: {},
controller: function($scope) {
$scope.element = '';
}
}
}
focus.$inject = [];
function focus() {
return {
restrict: 'E',
transclude: true,
template: '<div id="focus"><div ng-transclude></div></div>',
require: '^?mainContent', // also tried 'mainContent' && '^mainContent'
link: function(scope, elem, attrs, ctrl) {
ctrl.element = 'such wow';
}
};
}
(yes, I know this syntax isn't as common however it follows the style guides for my project)
Thanks in advance, any help is very much appreciated!

Related

how to pass multiple scope variables into custom directive in angularjs

I am trying to pass 2 scope variables from controller into a custom directive and having problem in accessing both of them.Model is same for the directive and controller.
Here is the code:
Html:
<myDirective data="var1" item="var2"></myDirective>
Controller:
$scope.var1="abc";
$scope.var2="xyz";
Directive:
app.directive('myDirective', function () {
return {
restrict: 'E', //E = element, A = attribute, C = class, M = comment
scope: {
var1: '='
var2:'='
},
templateUrl: 'myTemplate.html',
link: function ($scope, element, attrs) {
}
}
});
TemplateUrl: myTemplate.html
<div>{{var1}}</div> // This works
<div>{{var2}}</div> // This doesn't works
Any idea how can I use both?
Make these changes in your code
<popover data="var1" item="var2"></popover>
JS
app.directive('popover', function () {
return {
restrict: 'E', //E = element, A = attribute, C = class, M = comment
scope: {
data: '=',
item: '='
},
templateUrl: 'myTemplate.html',
link: function (scope, element, attrs) {
console.log(scope.data, scope.item);
}
}
});
Change your template to match the names declared in the DDO.
<myDirective var1="var1" var2="var2"></myDirective>
Avoid using data as an attribute name. That is a reserved prefix that is stripped during normalization. For more information on attribute normilization, see AngularJS Developer Guide - Directive Normilization.

Directives in object created during app lifetime doesn't work

I've created some basic directive. It works well if I use it with some objects in html file
<some-directive some-data="123"></some-directive>
But if I dynamically load this object to my webpage:
//getting html source as a string, then appending it to DOM:
elem.html("<some-directive some-data='123'></some-directive>");
The directive doesn't work (object is being added properly to DOM)
app.directive('someDirective', function (notes, parts) {
return {
restrict: 'AE',
scope: {
someData: '='
},
link: function (scope, elem, attrs) {
console.log("directive fired");
}
};
});
What can I do to make it work properly?
For dynamic directives, you have to use $compile service that compiles scope into template. Look at sample below, <some-directive-wrapper /> will add <some-directive /> element into itself and compile scope value
var app = angular.module('app', []);
app.directive('someDirective', function () {
return {
restrict: 'AE',
scope: {
someData: '='
},
template: '<h2>someDirective compiled, someData is {{someData}}</h2>',
link: function (scope, elem, attrs) {
console.log("directive fired");
}
};
});
app.directive('someDirectiveWrapper', function ($compile) {
return {
restrict: 'AE',
link: function (scope, elem, attrs) {
//get value from ajax maybe
//and set to scope
scope.data = 123;
//replace directive with another directive
elem.html('<h1>someDirectiveWrapper compiled </h1>\n<some-directive some-data="data"></some-directive>');
//compile scope value into template
$compile(elem.contents())(scope);
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<some-directive-wrapper></some-directive-wrapper>
</div>

AngularJS - Is this the right way to write a directive?

I was trying to declare a directive, it is apparently right but when I load it in html nothing occurs.
This is the code:
(function() {
'use strict';
var app = angular
.module('App');
app.directive('directiveFunction', directiveFunction);
function directiveFunction(){
return {
restrict: 'EA',
replace: true,
template: '<div>Example</div>',
controller: directiveController,
controllerAs: 'example',
bindToController: true,
link: linkFunction
}
}
linkFunction.$inject = ['$scope', 'elem', 'attrs', 'ctrl'];
function linkFunction(scope, element, attrs, ctrl) {}
function directiveController() {
var example = this;
}
})();
I call this in html as <directive-function></directive-function> but it does nothing.
I created a fiddle for you.. you are doing all well, I think that you are using it like
https://jsbin.com/koporel/edit?html,js,output
<directiveFunction></directiveFunction>
No, use - where case changes, like
<directive-function></directive-function>

AngularJS: transcluded with same controller

I have a directive that wraps another one like this :
<div direction from="origin" to="destination">
<div direction-map line-color="#e84c3d"></div>
</div>
the direction-map directive is transcluded, see my code (Fiddle available here) :
var directionController = function() {
//do stuffs
};
var directionMapController = function() {
//do other stuffs
};
var Direction = angular.module("direction", [])
.controller("directionController", directionController)
.controller("directionMapController", directionMapController)
.directive("direction", function() {
var directive = {
restrict: "AEC",
controller: "directionController",
scope: {},
transclude: true,
link: {
pre: function($scope, $element, attrs, controller, transclude) {
console.log("direction's controller is directionController : ");
console.log(controller.constructor === directionController);//true, that's ok
transclude($scope, function(clone) {
$element.append(clone);
});
}
}
};
return directive;
})
.directive("directionMap", function() {
var directive = {
require: "^direction",
controller: "directionMapController",
restrict: "AEC",
scope: true,
link: {
pre: function($scope, $element, $attrs, controller) {
console.log("directionMap's controller is directionMapController :");
console.log(controller.constructor===directionMapController);//false that's not OK!!!!
}
}
};
return directive;
});
So my question is:
Why my child directive direction-map gets as parameter the controller of its parent (I think it's because it is transcluded), is it possible to avoid this or should I just re-think my code ?
It's happening beacause you are using require: "^direction" if you remove this line the directive will get the controller of itself rather than the parent one.
Hope it help :)
Updated Fiddle

Why does this angularjs directive not show the bound document?

I have a directive with a bound doc model from controller. But the directive does not show the document?
HTML:
<div ng-app="myApp">TestApp:
<div ng-controller="TestController as Test">Testdoc controller: {{Test.doc}}
<br>
<test-me ng-init="abc=123" my-model="Test.doc">Testdoc directive: {{myDoc}} | {{abc}}</test-me>
</div>
</div>
JS:
var app = angular.module("myApp", []);
app.controller("TestController", function () {
this.doc = {
name: 'testname',
id: null
};
});
app.directive("testMe", function () {
return {
scope: {
myDoc: '=myModel'
},
link: function(scope, elem, attrs){
}
}
});
output HTML is still:
TestApp:
Testdoc controller: {"name":"testname","id":null}
Testdoc directive: <missing output of doc here>| 123
jsfiddle: http://jsfiddle.net/kx97y93k/14/
What i am doing wrong?
Solution was not to call {{myDoc}} in html directly but inside a template.
app.directive("testMe", function () {
return {
restrict: 'E',
template: '<div>Testdirective: {{myDoc}}<div>',
scope: {
myDoc: '=myModel'
},
link: function(scope, elem, attrs){
}
}
});
See updated jsfiddle: http://jsfiddle.net/kx97y93k/18/
Many thanks to #Mr_Green for that hint
add restrict : 'E' to the DDO, see below. Angular 1.2 uses restrict : 'A' if not explicitly set otherwise. For Angular 1.3 that became 'EA' and your directive would have worked. To make it work in your fiddle, change it as follows:
app.directive("testMe", function () {
return {
restrict : 'E',
scope: {
myDoc: '=myModel'
},
link: function(scope, elem, attrs){
}
}
});

Categories