I have a Problem with my AngularJS Directive named "showFileBrowser". I want to use Javascript in my Template but it will not be execute in my Browser. Here is my Code:
app.directive("showFileBrowser", function() {
return {
restrict: 'E',
template: '<script>$("#searchNote").fileTree({data: scope.filedata,sortable: false,selectable: false});</script>'
}
});
Someone know why I cant execute Javascript in a Directive or know how to do it?
You dont need to use the id, use 'element' directly.
app.directive("showFileBrowser", function() {
return {
restrict: 'E',
link: function($scope, element, attrs) {
$(element).fileTree({data: scope.filedata,sortable: false,selectable: false});
}
}
});
It works fine if I return a function, but i prefer return an Object.
app.directive("showFileBrowser", function() {
return function(scope, element, attr) {
$(element).fileTree({data: scope.filedata,sortable: false,selectable: false});
}
});
Related
I have a promise SharedData which return a variable service .template as well. The value is mytemplate with which I build an url that I ant to pass to templateUrl directive but without success.
app.directive('getLayout', function(SharedData) {
var buildUrl= '';
SharedData.then(function(service) {
buildUrl = service.template + '/layouts/home.html';
console.log(buildUrl); // return mytemplate/layouts/home.html which is the URL I want to use as templateUrl
});
return {
restrict: 'A',
link: function(scope, element, attrs) {...},
templateUrl: buildUrl
}
});
Thanks for helping me!
I resolve my issue using $templateRequest
app.directive('getLayout', function($templateRequest, SharedData) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
SharedData.then(function(service) {
myTemplate = $templateRequest(service.template + '/layouts/home.html');
Promise.resolve(myTemplate).then(function(value) {
element.html(value);
}, function(value) {
// not called
});
});
}
};
});
Here is a Plunker
Hope this will help some people :) and thanks to #Matthew Green
The docs seem to say that the templateUrl can be set asynchronously. However, I have not been able to show that applies to promises. So one way you can do this then while still using a promise would be to add the template to your element in the link function instead.
That would look something like this.
app.directive('getLayout', function($templateCache, SharedData) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
SharedData.then(function(templateName) {
element.html($templateCache.get(templateName));
});
}
}
});
Here is a plunkr to show a full working example. It assumes that the template is loaded into $templateCache so if it isn't you can do a $http.get() for the same effect.
Is there a way for not losing connection to the current controller when you are wrapping data with a directive ?
My problem is, that the directive within the wrapped template has no connection to the outside controller any more and so I can not execute the function.
Wrapping Directive:
myApp.directive('wrapContent', function() {
return {
restrict: "E",
scope: {
model: "=",
datas: "="
},
templateUrl: "./any/template.php",
link: function(scope, element, attr) {
// any
}
};
});
Directive within the wrapped Template
myApp.directive('doAction', function() {
return {
restrict: "A",
link: function(scope, elem, attrs) {
$(elem).click(function(e) {
scope.$apply(attrs.doAction);
});
}
}
});
Conroller:
lmsApp.controller('OutsideController', function ($scope){
$sope.sayHello = function() {
alert("hello");
};
});
HTML where I want to execute the function (template.php):
<div>
<do-action="sayHello()"></do-action>
</div>
How I call the wrapContent directive which is outside (Updated):
<div ng-controller="OutsideController">
<wrap-content model="any" datas="data_any"></wrap-content>
</div>
How can I execute the sayHello() function?
Thank you for your help! I would appreciate every answer.
wrapContent directive will be processed with the scope of controller.
DoAction directive will be processed with the isolateScope of wrapContent directive.
Solution1:
Get a reference to the sayHello function in wrapContent using '&' and execute it in event handler.
Solution2:
Instead of using scope in your event handler, use scope.$parent.
You should pass sayHallo function to your parent directive using &
myApp.directive('wrapContent', function() {
return {
restrict: "E",
scope: {
model: "=",
datas: "=",
sayHallo: "&"
},
templateUrl: "./any/template.php",
link: function(scope, element, attr) {
// any
}
};
});
HTML
<div ng-controller="OutsideController">
<wrap-content model="any" datas="data_any" sayHallo="sayHallo()"></wrap-content>
</div>
Then in your child directive, you will have sayHallo in your scope, to call it just do it this:
myApp.directive('doAction', function() {
return {
restrict: "A",
link: function(scope, elem, attrs) {
scope.sayHallo();
}
}
});
And you dont need pass it again. So your child directive should looks like this:
<div>
<do-action></do-action>
</div>
UPDATE
If you want to use all your parent model functions,without passing each function. In your child directive,just use scope.model to have access to model attributes and functions.
myApp.directive('doAction', function() {
return {
restrict: "A",
link: function(scope, elem, attrs) {
scope.model.sayHallo();
}
}
});
The directive does not work from the controller. how to fix it?
baseapp.directive('loading', function () {
alert('loading');
return {
restrict: 'E',
replace: true,
template: '<div class="loading">loading</div>',
link: function (scope, element, attr) {
scope.$watch('loading', function (val) {
if (val) {
element.addClass('show');
alert('show');
} else {
element.addClass('hide');
alert('hide');
}
});
}
}
});
baseapp.controller ('ListCtrl', function ($scope, $http) {
$scope.loading = true;
$http.get('/blog').success(function(data) {
$scope.users = data;
$scope.loading = false;
});
});
When you load a directive called. from the controller $ scope.loading = true;
Nothing happens
What I noticed is that your adding a class over and over element.addClass('show'); resulting in if true and later false: class='show hide show hide ...' and so forth, one quick way to correct this is to remove one of the classes or you can toggle class:
.directive('myDir', function() {
return {
restrict: 'E',
replace: true,
template: '<div class="loading">loading</div>',
link: function (scope, element, attr) {
scope.$watch('loading', function (val) {
if (val===true) {
element.addClass('show');
element.removeClass('hide');
} else {
element.toggleClass('hide');
element.removeClass('show');
}
});
}
}
});
Other than that it seems to be working just fine on my end:
Online Demo
Note: I recommend you not to use alerts for debugging use console.log instead.
If you read the official documentation: https://docs.angularjs.org/guide/directive
You can read this:
The restrict option is typically set to:
'A' - only matches attribute name
'E' - only matches element name
'C' - only matches class name
If you want to use it as a class like you do, then you have to specify :
require: 'C'
Whats the best way to assign a new value through a directive? A two way databinding.
I have a fiddle here where i tried. http://jsfiddle.net/user1572526/grLfD/2/ . But it dosen't work.
My directive:
myApp.directive('highlighter', function () {
return {
restrict: 'A',
replace: true,
scope: {
activeInput: '='
},
link: function (scope, element, attrs) {
element.bind('click', function () {
scope.activeInput = attrs.setInput
})
}
}
});
And my controller:
function MyCtrl($scope) {
$scope.active = {
value : true
};
}
And my view:
<h1 highlighter active-input="active.value" set-input="false">Click me to update Value in scope: {{active}}</h1>
So what i wanna do is update the scope.active with the given attribute setInput.
Any ideas what I'm doing wrong here?
With element.bind you leave the realm of Angular, so you need to tell Angular that something had happened. You do that with the scope.$apply function:
scope.$apply(function(){
scope.activeInput = attrs.setInput;
});
here is an updated jsfiddle.
I successfully made a jQuery plugin into a directive.
app.directive('bxSlider', function($timeout)
{
return {
restrict: 'A',
link: function(scope, element, attrs)
{
$timeout(function(){element.bxSlider(scope.$eval(attrs.bxSlider))},1);
}
}
});
In my controller (through a click function), I'd like to call a method that is public on the plugin, but I am not sure how to do that. I tried setting the directive to a variable and calling it that way from my controller, but I get the error of ...has no method...
What is the correct way to do this?
You could broadcast an event to trigger your plugin method.
app.directive('bxSlider', function($timeout)
{
return {
restrict: 'A',
link: function(scope, element, attrs)
{
var slider;
$timeout(function() {
slider = element.bxSlider(scope.$eval(attrs.bxSlider));
}, 1);
scope.$on('reload-slider', function() {
slider.reloadSlider();
});
}
}
});
Then in the controller function you use $scope.$broadcast('reload-slider').