I would create a glossary, using an AngularJS directive. I start with this fiddle
http://jsfiddle.net/angularjsdc/KRVSQ/
I want to change the directive and substitute the modal with a tooltip.
app.directive('glossaryTerm', function () {
return {
controller: 'Glossary',
restrict: 'E',
scope: { /* empty */
},
template: /*HERE MY TOOLTIP TEMPLATE*/,
replace: true,
transclude: true,
compile: function (tElement, tAttrs, transclude) {
return {
pre: function (scope) {
transclude(scope, function (clone) {
scope.term = clone[0].textContent.toLowerCase();
});
},
post: function (scope) {
// load the definition into scope
scope.getDefinition(scope.term);
}
}
}
}
});
Any suggestion? Ideas?
Thanks
In the Angular bootstrap ui example you had to:
include http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.11.0.js
import the module
var app = angular.module('app', ['app.services', 'ui.bootstrap']);
and surround the variables you were passing into tooltip with {{}}
template: '<span><a class="glossary-term" href="#" tooltip="{{glossary[term]}}">{{term}}</a></span>',
Here's the modified JSFiddle: http://jsfiddle.net/5DuSa/
Related
I have a directive that works correctly when RequireJS is not used, and I'm trying to migrate it to an application based on RequireJS.
The directive wraps an Angular UI modal, and uses transclude to populate the modal elements (modal elements are defined in the controller that declares the directive). The problem is that if loaded with RequireJS, the modal does not show ANY elements (i.e. it's empty).
This is the plunk of the directive that works correctly without RequireJS. You will see a modal populated with elements.
This is the plunk of the directive that is loaded with RequireJS. You will see that the modal is empty.
There are no errors thrown when the modal is displayed empty, so I'm not sure how to tackle this problem. Any help will be greatly appreciated.
This is the directive:
define(['app','uiBootstrap'], function (app) {
'use strict';
app.directive("theModal", function($timeout,$uibModal) {
return {
restrict: "AE",
scope: {
control: '='
},
transclude: true,
link: function (scope, element, attrs, ctrl, transclude) {
scope.control = scope.control || {}
scope.control.openModal = function () {
var instance = $uibModal.open({
animation: false,
scope: scope,
windowClass: 'the-modal',
template: '<div>in the template</div><div class="content"></div>',
appendTo: element
});
$timeout(function (){
transclude(scope.$parent, function(clonedContent){
element.find('.content').append(clonedContent);
})
},10);
};
}
}
});
});
And this is how I invoke it:
<div ng-controller="ctl">
<button ng-click="open()">open it!</button>
<div the-modal control="modalCtl">
<p>some text</p>
<input type="text" ng-model="input1" />
</div>
</div>
The issue is you have circular dependency. The app needs your modal module to display things correctly, but your modal directive needs that app. The solution is to load your modal directive into a separate module.
Define a separate Angular Module for Modal
// contents of modal.js (remove app dependency)
define(['uiBootstrap'], function () {
'use strict';
var mod = angular.module('modal', ['ui.bootstrap']);
mod.directive("theModal", function($timeout, $uibModal) {
return {
restrict: "AE",
scope: {
control: '='
},
transclude: true,
link: function (scope, element, attrs, ctrl, transclude){
// removed code for brevity
}
}
});
mod.directive("theButton", function($timeout) {
return {
restrict: "AE",
scope: {
control: '='
},
transclude: true,
link: function (scope, element, attrs, ctrl, transclude){
// removed code for brevity
}
}
});
return mod;
});
Make app depend on Modal
// contents of app.js
define([
'angular',
'uiBootstrap',
'uiRouter',
'modal' // <--- the modal.js directive
], function (angular) {
'use strict';
return angular.module('app', ['ui.bootstrap','ui.router', 'modal']); // <--- also add it here
});
I have a search box which I want to use as a custom directive. This is the code for it :
(function(angular) {
'use strict';
angular.module('searchApp', [])
.directive('searchBox', function () {
return {
restrict: 'E',
transclude: true,
scope: {
'btnclick': '&onClick'
},
link: function(scope, elem, attrs) {
});
});
},
templateUrl: 'search-box.html'
}
});
})(window.angular);
In the link part, I need a function that has some JSON data. And then, a directive should have a controller that invokes that function and passes it to the parent scope.
Please show me code for the link function and the controller.
Recently I use angular to develop a directive, there is an directive which like ng-repeat to generate some records, I used transclude to implement it. but it raise an error that "Controller 'aArea', required by directive 'bSpan', can't be found!".
1. ModuleA code
var moduleA = angular.module("moduleA", []);
moduleA.directive("aArea", function () {
return {
restrict: 'E',
transclude:'element',
scope: {
amount:"="
},
template: '<div id=\"cc\" ng-transclude></div>',
controller: function ($scope,$element,$attrs) {
this.getData = function (data) {
return data + " is ok";
}
},
compile: function (tElement, attrs, linker) {
var parentElement = tElement.parent();
return {
pre: function () {
},
post: function (scope) {
linker(scope.$parent,function (clone,scope) {
parentElement.append(clone);
});
linker(scope.$parent, function (clone, scope) {
parentElement.append(clone);
});
linker(scope.$parent, function (clone, scope) {
parentElement.append(clone);
});
}
}
}
}
});
moduleA.directive("bSpan", function () {
return {
restrict: 'E',
scope: {
data: "=",
},
template: '<span style=\"background-color:gray;color:orange\">{{data}}</span>',
require: "^aArea",
link: function ($scope, $element, $attrs, controller) {
var data = "abc";
}
}
});
2. ModuleB COde
var moduleB = angular.module("moduleB", []);
moduleB.directive("myItem", function () {
return {
restrict: 'E',
scope: {
item: "=",
itemTemplate: '='
},
priority: 1000,
terminal:false,
template: '<ng-include src=\"itemTemplate\"/>',
controller: function ($scope, $element, $attrs) {
var data = "";
}
}
})
3. ModuleC Code
var moduleC = angular.module("moduleC", ["moduleA", "moduleB"]);
moduleC.controller("Ctr", function ($scope) {
$scope.item = {};
$scope.item.dataAmount = 1000;
$scope.item.templateUrl = "item-template.html";
})
4. Html Code
<body>
<div ng-app="moduleC">
<div ng-controller="Ctr">
<a-area>
<my-item item="item" item-template="item.templateUrl"></my-item>
</a-area>
</div>
</div>
</body>
5. template code
<div>
<span style="display:block">hello every one</span>
<b-span data="item.dataAmount"></b-span>
</div>
You should not use the transclude function (that you called linker) of the compile function - it is deprecated.
From $compile documentation:
Note: The transclude function that is passed to the compile function is deprecated, as it e.g. does not know about the right outer scope. Please use the transclude function that is passed to the link function instead.
Following this guidance (and a few other minor changes for the better), change the aArea directive as follows:
compile: function(tElement, tAttrs) {
// don't use the template element
//var parentElement = tElement.parent();
return function(scope, element, attrs, ctrls, transclude) {
transclude(function(clone, scope) {
element.after(clone);
});
transclude(function(clone, scope) {
element.after(clone);
});
transclude(function(clone, scope) {
element.after(clone);
});
};
}
In fact, you don't even need the transclude function at all and you don't need to do transclude: "element". You could just change to transclude: true and use <div ng-transclude> 3 times in the template.
I've seen the typical ('myContainer').select(); in Jquery. However, is there a way to select text within a .container div with Angular? I cannot find anything in the API reference and every search references the select element.
Angular does have .text() in its jQLite1.
You'd call it in a directive like:
angular.module('demo', [])
.directive('someDirective', function(){
return {
restrict: 'E',
templateUrl: 'template.html',
transclude: true,
scope: true,
link: function(scope, element, attrs) {
scope.content = {
changeText: function() {
button = element.find('button');
button.text('Nice new button')
}
}
}
}
}
)
I have a setup like this:
<controller>
<directive>
in my controller that has a function that returns an html string. How can I get my directive to render this by accessing the controllers scope?
Or maybe I should just put the controller in the directive?
app.controller('controller', ['$scope', 'DataService', function ($scope, DataService) {
$scope.parseJson = function () {
//returns the html
};
}]);
directive
app.directive('Output', function () {
return {
restrict: 'A',
replace: true,
template: '<need html from controller>',
link: function(scope, element, attr) {
//render
//scope.parseJson();
}
};
});
You should use the isolated scope: '&' option
app.directive('output', ['$sce', function ($sce) {
return {
restrict: 'A',
replace: true,
template: "<div ng-bind-html='parsed'></div>",
scope:{
output: "&"
},
link: function(scope){
scope.parsed = $sce.trustAsHtml(scope.output());
}
};
}]);
Template:
<div output="parseJson()"></div>
The directive and the controller should be sharing the scope already. Don't bother using a template for the directive, just get the HTML string in you linking function (you already have the method call in there) and modify the element directly using element.html(). Take a look at the element docs for more info.
app.directive('Output', function ($compile) {
return {
restrict: 'A',
link: function(scope, element, attr) {
var templateString = scope.parseJson();
var compiledTemplate = $compile(templateString)(scope);
compiledTemplate.appendTo("TheElementYouWishtoAppendYourDirectiveTo");
}
};
});