how to add dynamic element(template) in angular - angularjs

Template append content dynamically with value and color like below image using angular. Dynamically create DOM element from back end value with predefined templates.
What elements used in angular js?
directive
template
How to sort the directive in angular JS using Jquery ui sortable?
.directive('contentItem',function($compile){
var imageTemplate = '<div class="mypanel mypanel-default portlet" ng-class="{fullscreen : fullscreen}" ng-show="close">'+
'<div class="mypanel-heading">'+
'<div class="mypanel-btn" >'+
'<i class="{{fullscreenicon}}"></i>'+
'<i class="{{minimizeicon}}"></i>'+
'<i class="fa fa-times"></i>'+
'</div>'+
'<h5 class="mypanel-title">Optional Sizes</h5>'+
'</div>'+
'<div class="mypanel-body" ng-show="on">'+
'<div id="area-chart" class="height300">'+
'</div>'+
'</div>'+
'</div>';
var getTemplate = function(contentType) {
var template = '';
switch(contentType) {
case 'image':
template = imageTemplate;
break;
case 'video':
template = imageTemplate;
break;
case 'notes':
template = imageTemplate;
break;
}
return template;
}
var linker = function(scope, element, attrs) {
scope.on = true;
scope.tooltipminimize = 'Minimize';
scope.minimizeicon = 'fa fa-minus';
scope.fullscreenicon = 'fa fa-expand';
scope.tooltipfullscreen = 'Fullscreen';
scope.fullscreen = false;
scope.close = true;
scope.toggle = function () {
scope.on = !scope.on;
if(scope.tooltipminimize == 'Minimize'){
scope.minimizeicon = 'fa fa-plus';
scope.tooltipminimize = 'Maximize';
}
else{
scope.tooltipminimize = 'Minimize';
scope.minimizeicon = 'fa fa-minus';
}
};
scope.toggleHide = function () {
scope.close = !scope.close;
};
scope.toggleFullscreen = function(){
scope.fullscreen = !scope.fullscreen;
if(scope.tooltipfullscreen == 'Fullscreen'){
scope.fullscreenicon = 'fa fa-compress';
scope.tooltipfullscreen = 'Exit Fullscreen';
}
else{
scope.fullscreenicon = 'fa fa-expand';
scope.tooltipfullscreen = 'Fullscreen';
}
};
scope.sortableOptions = {
connectWith: '.sortable',
item: '.portlet',
placeholder: 'placeholder',
dropOnEmpty: true
};
scope.rootDirectory = 'images/';
element.html(getTemplate('image')).show();
$compile(element.contents())(scope);
}
return{
restrict: "E",
link: linker,
scope:true
};
});

This is definitely a case for a directive. Pass in your arguments, and use the link function to basically build up the template from strings. In the example below, I'm taking parameters to build up inputs for a form.
.directive('qrunChild', ['$compile', function ($compile) {
return {
restrict: 'AE',
require: 'ngModel',
scope: {
ngModel: '=',
},
link: function (scope, element, iAttrs, ngModelController) {
var tpl = '';
var bpstart = '<div class="row no-margin">';
var bp = ' <span class="pull-left"><i class="fa fa-circle text-xs text-info-lt m-r-xs pull-left"></i>{{ngModel.name}}</span><span class="badge pull-right">{{ngModel.type}}</span>';
var bpend = '</div class="row">';
if (scope.ngModel.type == 'text') {
//tpl = '<input type="text" ng-model="ngModel.type">';
}
else if (scope.ngModel.type == 'mc') {
tpl = '<div ng-repeat="opt in ngModel.options"><label class="ui-checks option"><input type="radio" ng-model="ngModel.optionsSelected" value="{{opt.name}}"><i style="margin-right:20px;"></i>{{opt.name}}</label></div>';
}
view = $compile(bpstart + bp + tpl + bpend)(scope);
return $(element).html(view);
}
};
}])
I could call this as follows in my HTML:
Edit: if you wanted to provide a URL to the template instead, you could do something like this (in this case, it's just taking an argument called item.templateUrl in the parent scope):
.directive('dynamicTemplate', function () {
return {
template: '<ng-include src="getTemplateUrl()"/>',
scope: false,
transclude: true,
restrict: 'E',
controller: function ($scope) {
$scope.getTemplateUrl = function () {
//resolve the template
return $scope.item.templateUrl;
}
}
};
})

Related

Set focus of text box in directive

I'm experimenting with an inline-edit directive form here: http://icelab.com.au/articles/levelling-up-with-angularjs-building-a-reusable-click-to-edit-directive/
I would like to know how to set the cursor in the text box that gets created when I click some text to be edited.
Here is the directive with a few minor changes to the template:
.directive("clickToEdit", function() {
var editorTemplate = '<div class="click-to-edit">' +
'<div ng-hide="view.editorEnabled" ng-click="enableEditor()">' +
'{{value}} ' +
'</div>' +
'<div ng-show="view.editorEnabled">' +
'<input ng-model="view.editableValue" ng-blur="save()">' +
'</div>' +
'</div>';
return {
restrict: "A",
replace: true,
template: editorTemplate,
scope: {
value: "=clickToEdit",
},
controller: function($scope) {
$scope.view = {
editableValue: $scope.value,
editorEnabled: false
};
$scope.enableEditor = function() {
$scope.view.editorEnabled = true;
$scope.view.editableValue = $scope.value;
};
$scope.disableEditor = function() {
$scope.view.editorEnabled = false;
};
$scope.save = function() {
$scope.value = $scope.view.editableValue;
$scope.disableEditor();
};
}
};
});
you need to add a link function like this :
link : function(scope, ele, attrs) {
scope.$watch('view.editorEnabled', function(n, o) {
if(n) ele.find('input')[0].focus();
})
}

directive with nested directive and repeat not rendering

I have 2 directives, one of them is recursive and the other renders a form with a select option. Everything appears to be working, but the select box is empty in the ui but the angular comment is inside of the inspection. I have tried to compile the result in multiple way but I cannot get the options to appear. The options are in a repeat and I think that is what is causing it. Here are my 2 directives. Thanks for the help.
select options
angular.module('myApp').directive("typesControl",function($compile,$timeout){
return {
replace: true
//THESE OPTIONS DO NOT SHOW UP IN THIS SELECT
,template: '<select name="name" class="form-control"><option ng-repeat="type in design.types" ng-selected="{{type.id == content.partid}}">{{type.name}}</option></select>'
,compile: function (element, link) {
var contents = element.contents().remove();
var compiledContents;
return {
pre: function (scope, element) {
}
,post: function (scope, element) {
if (!compiledContents) {
compiledContents = $compile(contents);
}
compiledContents(scope, function (clone) {
element.append(clone);
});
element.change(function () {
var val = $(this).find('option:selected').val();
var $form = $(this).closest('form');
var $row = $(this).closest('.row');
var $container = $form.find('.formtemplate');
var tpl = '';
//THESE INPUTS DO RENDER
tpl += '<div><input type="text" name="ids" placeholder="ids" class="form-control" value="{{content.ids}}"></div>';
tpl += '<div><input type="text" name="classes" placeholder="classes" class="form-control" value="{{content.classes}}"></div>';
switch (val) {
case 'Partial':
tpl += '<select name="content" class="form-control"><option ng-repeat="link in links" ng-selected="{{link.url == content.content}}">{{link.url}}</option></select>';
break;
case 'View':
break;
case 'Source':
break;
}
element.removeAttr('types-control');
$container.empty().append(tpl);
$compile($container)(scope);
if (!scope.$$phase) {
scope.$apply();
}
});
$timeout(function () {
element.trigger('change');
});
}
};
}
}
});
recursive directive
angular.module('myApp').directive("tree", function($compile,$timeout) {
return {
scope: {family: '='}
,template:
'<div class="row" ng-repeat="content in family | orderObjectBy:\'orderby\':false" style="margin-top: 25px;">'+
'<div class="col-lg-6">'+
'<form class="simple-form">'+
'<div types-control ></div>'+
'<div class="formtemplate"></div>'+
'<button ng-click="newcontent(content.id)" type="submit" class="btn btn-success glyphicon glyphicon-plus"></button>'+
'<button ng-click="deletecontent(content.id)" type="submit" class="btn btn-danger glyphicon glyphicon-minus"></button>'+
'</form>'+
'</div>'+
'<div tree family="content.children"></div>'+
'</div>'
,compile: function(element, link){
var contents = element.contents().remove();
var compiledContents;
return {
pre: function(scope, element){
}
,post: function(scope, element){
if(!compiledContents){
compiledContents = $compile(contents);
}
compiledContents(scope, function(clone){
element.append(clone);
});
}
};
}
};
});
EDIT: I created this Plunker which shows the problem with the select boxes.
Just in case someone else runs into this problem, it is related to the scope. Using scope inside a directive the way that I am passing family in creates an isolated scope. This means that you have to pass the other variables in using attributes. Working Plunker
scope: {
family: '='
,links: '='
,types: '='
}

Angularjs autocomplete in already created directives

I already have a directive for inputbox. i need to implement Autocomplete feature on that
here is my directive code
app.directive("bhAddCategory", ["$rootScope", "$timeout",function($rootScope, $timeout) {
return {
scope: {
rmText: '=bhRmText'
},
replace: true,
template: '<div>' +
'<div class="pull-left forDrop"><input type="text" focus-on="focusMe" ng-class="myColonyList" class="effect1" placeholder="Add a colony" data-ng-model="newCategoryName" data-ng-trim="true" ng-keypress="pressEnter($event)"></div>' +
'<div class="pull-right"><img src="/images/greyplus.png" ng-class="{imageoverflow: imageOverflow}" ng-show="loadplus" data-ng-click="addCategory()" alt="add category"><img src="/images/loader.gif" ng-class="{imageoverflow: imageOverflow}" alt="" ng-show="loadgif" class="colonyloder"></div >' +
'</div>',
link: function(scope, element, attrs) {
scope.loadplus = true;
scope.pressEnter = function(keyEvent) {
if (keyEvent.which === 13)
scope.addCategory();
};
scope.resetNewCategoryName = function() {
if (scope.rmText) {
scope.newCategoryName = '';
}
};
}
};
}]);
How can i implement Auto complete here.
Any Suggestions
Thanks

Angular.js Directive Template - If Then Conditional For What Template To Use

In angular.js, for the directive I would like to specify the property of the template key according to what the attr.checkType is using with if then. How could I do this? The only place I know to place logic would be in the link function, but the template key/property goes outside the link function.
angular.module('monitorApp')
.directive("countDown", [ 'sseHandler', function (sseHandler) {
function _bindMessage(scope, message) {
scope.countFrom = message;
}
return {
restrict: 'E',
scope: {
countFrom: "=",
checkType: "#"
},
//WOULD LIKE TO PLACE IF THEN TO SPECIFY WHAT TYPE OF TEMPLATE TO
//USE ACCORDING TO ATTR.CHECKTYPE.
template : if (attr.checkType == "foo") {
'<div class="btn btn-block btn-inverse" id="api-time">'+
'Next update in &nbsp <span class="info-test">{{countFrom}}</span>'+
'&nbsp seconds} else
{
<h1> HI </h1>
},
link: function(scope, element, attr){
scope.countFrom = sseHandler.broadcastStamp[attr.checkType] || "initializing";
scope.$on('ONE_SEC', function() {
resultType = attr.checkType;
seconds = sseHandler.broadcastStamp[attr.checkType];
if (seconds < -3) {
seconds = "Snap! Broadcast is late." +
" Something is broke";
}
else if (seconds <0) {
seconds = "running a little late";
}
_bindMessage(scope,seconds);
});
}
}
}]);
You simply need to use a single template, and use ng-if inside the template:
template : '<div>' +
'<div ng-if="checkType == 'foo'" class="btn btn-block btn-inverse" id="api-time">'+
'Next update in &nbsp <span class="info-test">{{countFrom}}</span>'+
'&nbsp seconds}' +
'</div>' +
'<h1 ng-if="checkType != 'foo'">HI</h1>' +
'</div>'
Below you'll find a directive that choose among a list of templates according to the "temp" attribute value
module.directive('templateSwitch', ['$compile', function ($compile) {
var getTemplate = function (Type) {
var typelist = {
template1: '<div>view1</div>',
template2: '<div>view2</div>'
};
return typelist[Type];
}
return {
restrict: 'E',
link: function (scope, element, attrs) {
var templatelinker = function (listType) {
var html = getTemplate(listType);
element.html(html).show();
$compile(element.contents())(scope);
};
templatelinker(attrs.temp);
}
};
}])
Use it as follow
<template-switch temp="template2"></template-switch>

Dynamic template in AngularJS Directive (Not templatUrl)

I have seen the ability to have a dynamic templateUrl within a Directive in Angular but while researching I have yet to see a dynamic template.
.directive('col', function () {
var template = '<div class="one" ng-transclude></div>';
return {
restrict: 'E',
scope: {},
transclude: true,
replace: true,
template: template,
link: function (scope, ele, attrs) {
if (attrs.two !== undefined) {
template = '<div class="two" ng-transclude></div>';
} else if (attrs.three !== undefined) {
template = '<div class="three" ng-transclude></div>';
} else {
template = '<div class="one" ng-transclude></div>';
}
console.log(template);
}
};
})
HTML:
<col three>Three</col>
<col two>Two</col>
<col>Nothing</col>
The console shows appropriately:
<div class="three" ng-transclude></div>
<div class="two" ng-transclude></div>
<div class="one" ng-transclude></div>
However the output shows the default / initial <div class="one" ng-transclude></div>
This is because the template is collected before the link function is fired, if your only trying to change the classes then just do something like this.
.directive('col', function () {
var template = '<div class="{{class}}" ng-transclude></div>';
return {
restrict: 'E',
scope: {},
transclude: true,
replace: true,
template: template,
link: function (scope, ele, attrs) {
$scope.class = attrs.three ? 'three' : attrs.two ?'two' : attrs.one ? 'one' : '';
}
};
});
Other than that I don't know how else you would accomplish it.
When you say 'template = 'xxx' in your link function it is referencing your template variable, not the property on the returned object. Try this:
.directive('col', function () {
var result = {
restrict: 'E',
scope: {},
transclude: true,
replace: true,
template: template,
link: function (scope, ele, attrs) {
if (attrs.two !== undefined) {
result.template = '<div class="two" ng-transclude></div>';
} else if (attrs.three !== undefined) {
result.template = '<div class="three" ng-transclude></div>';
} else {
result.template = '<div class="one" ng-transclude></div>';
}
console.log(result.template);
}
};
return result;
})
If the template is dynamically constructed based on the attributes then you can just supply a template function passing in the attributes
.directive('col', function () {
return {
restrict: 'E',
scope: {},
transclude: true,
replace: true,
template: function(element, attrs) {
var template = null;
if (attrs.two !== undefined) {
template = '<div class="two" ng-transclude></div>';
} else if (attrs.three !== undefined) {
template = '<div class="three" ng-transclude></div>';
} else {
template = '<div class="one" ng-transclude></div>';
}
return template;
},
link: function (scope, element, attrs) {
}
};
})
If the template is dynamically constructed based on the model then it's bit more involved. Note that the transclusion is done explicitly rather than using the ng-transclude directive.
.directive('col', function () {
return {
restrict: 'E',
scope: {
myVariable: '='
},
transclude: true,
replace: true,
link: function (scope, element, attrs, nullController, transclude) {
var template = null;
if (scope.myVariable == 'two') {
template = '<div class="two"></div>';
} else if (scope.myVariable == 'three') {
template = '<div class="three"></div>';
} else {
template = '<div class="one"></div>';
}
element.html(template);
$compile(element.contents())(scope);
transclude(scope.$parent, function(clone, scope) {
element.children().append(clone);
});
}
};
})

Resources