Angular toggle directive from parent controller - angularjs

How i can show/hide directive when some elements in parent controller has event?
app.directive('rest', function(){
return {
restrict: 'E',
scope: false,
replace: true,
link: function(scope, elem, attr) {
},
templateUrl: '<div ng-show="showDirective"></div>',
}
});
<div ng-controller="AppCtrl">
<rest></rest>
<div ng-click="showDirective = false"><div> <!-- hide directive -->
<div ng-click="showDirective = true"><div> <!-- show directive -->
</div>

Here, your mistake was "templateUrl" instead of "template". When you provide html inline, user "template", when you provide html in a separate html file, use "templateUrl" and provide a url to the template html:
http://plnkr.co/edit/xzqOvcjKYfWxazWfHWyS?p=preview
.directive('rest', function(){
return {
restrict: 'E',
scope: false,
replace: true,
link: function(scope, elem, attr) {
},
template: '<div ng-if = "showDirective" >Test</div>',
}

Related

Get image src within directive

I have a directive with an img tag inside it.
angular.module('example')
.directive('customDirective', function() {
return {
restrict: 'E',
replace: true,
transclude: true,
scope: {}, //isolate scope
templateUrl: 'directives/customDirective.html'
link: function(scope, element, attrs) {
// returns undefined
console.log(element.find('img').src);
}
};
});
the directive template:
<div class="customDirective">
<img src="image.jpg" />
</div>
I'm trying to get a hold of the src attribute on the image tag.
var src = element.find('img').attr('src');
This is assuming there is only a single img tag.
It would probably be easier to set the source in your directive.
Directive
angular.module('example')
.directive('customDirective', function() {
return {
restrict: 'E',
replace: true,
transclude: true,
templateUrl: 'directives/customDirective.html'
link: function(scope, element, attrs) {
scope.imgSrc = 'image.jpg';
}
};
});
Template
<div class="customDirective">
<img ng-src="{{imgSrc}}" />
</div>
Then your code drives the template instead of you needing to read data out of the template.

Add html content after directive template

Having this HTML :
<div messages>
Some content...
</div>
This directive :
myAppDirectives.directive("messages", function () {
return {
restrict: 'A',
templateUrl: '/directives/messages/messages.html',
link: function (scope, elem, attrs) {
//...
}
};
});
And messages.html :
<p>message1</p>
<p>message2</p>
The content of my html gets replaced by the directive template but i'd like it to just be appended.
Html becomes this :
<div messages>
<p>message1</p>
<p>message2</p>
</div>
But I'd like this :
<div messages>
<p>message1</p>
<p>message2</p>
Some content...
</div>
Is this possible without using ng-include?
This looks like a perfect situation to use ngTransclude.
Try:
myAppDirectives.directive("messages", function () {
return {
restrict: 'A',
transclude: true,
templateUrl: '/directives/messages/messages.html',
link: function (scope, elem, attrs) {
//...
}
};
});
messages.html:
<p>message1</p>
<p>message2</p>
<ng-transclude></ng-transclude>
If you really want this behaviour, use transclusion:
myAppDirectives.directive("messages", function () {
return {
restrict: 'A',
transclude: true,
templateUrl: '/directives/messages/messages.html',
link: function (scope, elem, attrs) {
//...
}
};
});
And the template becomes:
<p>message1</p>
<p>message2</p>
<span ng-transclude></span>
The original content of the <div messages> element will be wrapped in the <span ng-transclude>, but this should not harm.

Prevent angular from copying attributes when replace=true

The following directive:
var app = angular.module('demo', []);
app.directive('myDirective', function() {
return {
restrict: 'E',
template: '<h1>Foo bar</h1>'
};
});
With the following usage:
<my:directive foo="bar"></my:directive>
Renders the following HTML:
<my:directive foo="bar"><h1>Foo bar</h1></my:directive>
Since I want to replace my directive with the provided template I set replace:true. This produces the following HTML:
<h1 foo="bar">Foo bar</h1>
Note that Angular copies my directive's attributes to the template elements (the foo="bar"). How can I prevent this behaviour?
You can manually remove the attributes in the link function of the directive:
.directive('myDirective', function() {
return {
restrict: 'E',
replace: true,
template: '<h1>Foo bar</h1>',
link: function(scope, elm, attrs){
elm.removeAttr('foo');
}
};
});
Here's a fiddle with this directive working in your situation.
EDIT: You can extend this to remove all attributes dynamically with a simple loop:
.directive('myDirective', function() {
return {
restrict: 'E',
replace: true,
template: '<h1>Foo bar</h1>',
link: function(scope, elm, attrs){
for(var attr in attrs.$attr){
elm.removeAttr(attr);
}
}
};
});

AngularJS How to access elements inside directive before they get replaced

How do I get the input element from within the directive before the template overwrites the contents?
html
<div xxx>
<input a="1" />
</div>
js
app.directive('xxx', function(){
return {
restrict: 'A',
template: '<p></p>',
replace: true, //if false, just leaves the parent div, still no input
compile: function(element, attrs) {
console.log(element);
return function (scope, iElement, iAttrs) {
}
}
};
});
i am on angular 1.0.x, I cannot pass in optional scope parameters with the '=?' syntax and i want to be able to override a portion of the default template of the directive in a very flexible way. instead of adding a scope variable or attribute everytime that I just plan on passing through the directive, I want to be able to supply the whole element to be used.
edit
the input must retain the scope of the directive, and not the parent.
edit
I am trying to include a partial template inside a directive that will overwrite a piece of the actual template. The piece I am including therefore needs to have access to the directive's scope and not the parent's.
Update
It seems if I do not provide a template or a template URL and instead replace the contents manually using the $templateCache I can have access to the inner elements. I want to let angular handle the template and the replacement though and just want to be able to access the contents in the directive naturally before they get replaced.
Solution
Plunkr
html
<body ng-controller="MainCtrl">
<div editable="obj.email">
<input validate-email="error message" ng-model="obj.email" name="contactEmail" type="text" />
</div>
</body>
js
app.controller('MainCtrl', function($scope) {
$scope.obj = {
email: 'xxx'
};
});
app.directive('editable', function($log){
return {
restrict: 'A',
transclude: true,
template: '<div ng-show="localScopeVar">{{value}}<div ng-transclude></div></div>',
scope: {
value: '=editable'
},
link: function(scope) {
scope.localScopeVar = true;
}
};
});
app.directive('validateEmail', function($log){
return {
restrict: 'A',
require: 'ngModel',
scope: true,
link: function(scope, el, attrs, ctrl) {
console.log(attrs['validateEmail']);
}
};
});
I believe you're looking for the transclude function (link is to 1.0.8 docs). You can see what's going on with:
app.directive('xxx', function($log){
return {
restrict: 'A',
transclude: true,
compile: function(element, attrs, transclude) {
$log.info("every instance element:", element);
return function (scope, iElement, iAttrs) {
$log.info("this instance element:", element);
transclude(scope, function(clone){
$log.info("clone:", clone);
});
}
}
};
});

Accessing parent's parent controllers through Angular require attribute

In the below example, the accordion-group directive shares a controller and scope with the parent accordion, using the "require: '^accordion'" attribute within the accordion-group directive.
If I wanted to create a child directive, under accordion-group, how would it access the accordion controller as well? Requiring ^accordion and ^accordionGroup do not seem to work.
https://github.com/angular-ui/bootstrap/blob/master/src/accordion/accordion.js
It does work that way. I was just being stupid.
Fiddle for posterity here.
'use strict';
angular.module('myApp', []).controller('OneController', function() {
this.test = function(element) {
element.css('color', 'red');
}
}).directive('one', function() {
return {
restrict: 'E',
transclude: true,
replace: true,
controller: 'OneController',
template: '<span ng-transclude>And a </span>',
}
}).directive('two', function() {
return {
restrict: 'E',
transclude: true,
replace: true,
require: '^one',
template: '<span ng-transclude>and a </span>',
}
}).directive('three', function() {
return {
restrict: 'E',
transclude: true,
replace: true,
require: '^one',
template: '<span ng-transclude>and a one two</span>',
link: function(scope, element, attrs, ctrl) {
ctrl.test(element);
}
}
});

Resources