Angularjs autocomplete in already created directives - angularjs

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

Related

$watch doesn't triggered in directive

i have a directive:
function templateFn() {
return '<div class="card-wrapper">'
+ '<div class="cards-carousel">'
+ '<div class="cards-carousel-inner">'
+ '<div ng-repeat="item in cards">'
+ '<div class="item" ng-class="{\'active\': $index == $parent.ngModel.id, \'next\' : $index == $parent.ngModel.id + 1, \'prev\' : $index == $parent.ngModel.id - 1}">'
+ '<label><input id="{{item.eid}}" type="radio" ng-value="item" ng-model="$parent.ngModel">'
+ '<img alt="{{item.id}}" ng-src="{{item.url}}" /></label>'
+ '</div>'
+ '</div>'
+ '</div>'
+ '</div>'
+ '</div>';
}
function linkFn(scope, element, attrs) {
scope.cards = JSON.parse(attrs.cards);
scope.$watchCollection('cards', function(newValue, oldValue) {
if (newValue !== oldValue) {
scope.cards = newValue;
}
}, true);
}
return {
restrict: 'E',
required: ['ngModel'],
scope: {
ngModel: '='
},
link: linkFn,
replace: 'true',
template: templateFn
};
and in controller i make rest request to take needed cards. Cards pushed like this: ctrl.cardList.push(card)
This is my view:
<ab-card-carousel cards="{{ctrl.cardList}}"
ng-model="ctrl.debitCardItem">
</ab-card-carousel>
and in the view, when i console.log({{ctrl.cardList}}) it renders good, and as i need, but changes not made in scope.$watch function.
Can anybody help me?
Remove the interpolation from the attribute:
<ab-card-carousel ̶c̶a̶r̶d̶s̶=̶"̶{̶{̶c̶t̶r̶l̶.̶c̶a̶r̶d̶L̶i̶s̶t̶}̶}̶"̶
cards="ctrl.cardList"
ng-model="ctrl.debitCardItem">
</ab-card-carousel>
Add one-way binding:
scope: {
ngModel: '=',
cards: "<",
},
Change the linkFn to:
function linkFn(scope, element, attrs) {
̶s̶c̶o̶p̶e̶.̶c̶a̶r̶d̶s̶ ̶=̶ ̶J̶S̶O̶N̶.̶p̶a̶r̶s̶e̶(̶a̶t̶t̶r̶s̶.̶c̶a̶r̶d̶s̶)̶;̶
scope.$watchCollection('cards', function(newValue, oldValue) {
if (newValue !== oldValue) {
scope.cards = newValue;
}
}, true);
}

Angular js : How i can change the color of accordion active on click

How can I change the color of an active accordion when I click on the glyphicon using ng-if. I have this code: I can't succeeded to do that
have you an idea please. Thanks an advance.
style.css:
selectionAccordion {
&:hover, &:focus {
color: White;
background-color:Blue;
}
}
.directive('accordion', function () {
return {
restrict: 'EA',
replace: true,
transclude: true,
template: '<div data-ng-transclude=""></div>',
controller: function () {
var Spots = [];
this.Open = function (selected_Spot) {
angular.forEach(Spots, function (Spot) {
if (selected_Spot != Spot)
Spot.showMe = false;
});
};
this.addSpot = function (Spot) {
Spots.push(Spot);
};
}
};
})
.directive('spotcam', function () {
return {
restrict: 'EA',
replace: true,
transclude: true,
require: '^accordion',
scope: { title: '#' },
template: '<div>' +
'<div class="title selectedAccordionStyle ng-if="true"><a class=" more-less glyphicon glyphicon-plus" ng-class="{true: \'glyphicon glyphicon-minus\', false:\'glyphicon glyphicon-plus\'}[showMe]" data-ng-click="toggle()"></a>{{title}}</div>' +
'<div class="body" data-ng-show="showMe" data-ng-transclude=""></div>' +
'</div>',
link: function (scope, element, attrs, accordionController)
scope.showMe = false;
accordionController.addSpot(scope);
scope.toggle = function () {
scope.showMe = !scope.showMe;
accordionController.Open(scope);
} } }
});
thanks an advance
You could use the same condition as on the nested a-tag which checks if the accordion is selected by the value showMe.
template: '<div>' +
'<div class="title" ng-class="{true: \'selectedAccordionStyle\', false:\'\'}[showMe]"><a class=" more-less glyphicon glyphicon-plus" ng-class="{true: \'glyphicon glyphicon-minus\', false:\'glyphicon glyphicon-plus\'}[showMe]" data-ng-click="toggle()"></a>{{title}}</div>' +
'<div class="body" data-ng-show="showMe" data-ng-transclude=""></div>' +
'</div>',

Error: [$compile:ctreq] data passing between two directive from different module

I have two different module in which I have two directives. I need to pass data between these two directive. I use require property. but I get some error
Error: [$compile:ctreq] Controller 'yearSort', required by directive 'budgetSort', can't be found!
My first directive is
angular.module('movieApp.yearsort.directives', []).directive('yearSort',[function(){
return{
restrict : 'AEC',
replace : true,
transclude : true,
controller : 'YearsortController',
templateUrl : 'app/components/yearsort/yearsort.html',
};
}]);
In the YearsortController I have the code
angular.module('movieApp.yearsort.controller', []).controller('YearsortController', ['$scope','HomeFactory','$timeout','$state',function($scope,HomeFactory,$timeout,$state) {
this.sayHello = function() {
$scope.words = "my requier";
console.log( $scope.words);
};
}]);
In my second directive I have the code
angular.module('movieApp.budgetsort.directives', []).directive('budgetSort',[function(){
return{
restrict : 'AEC',
replace : true,
transclude : true,
controller : 'BudgetsortController',
templateUrl : 'app/components/budgetSort/budgetSort.html',
require : "yearSort",
link : function(scope,element, attrs, demoCtrl){
demoCtrl.sayHello();
}
};
}]);
Why don't you try using a Service/Factory? It is a good option when you need to pass data through components or directives
I've made this plunkr to explain: http://plnkr.co/edit/V7BLbOrrtNhXl1QlUKxA?p=preview
HTML:
<body ng-controller="myCtrl">
<first-directive></first-directive>
<second-directive></second-directive>
</body>
Javascript:
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, dataService) {
$scope.name = 'World';
//set up the items.
angular.copy([ { name: 'test'} , { name: 'foo' } ], dataService.items);
});
app.directive('firstDirective', function(dataService){
return {
restrict: 'E',
template: '<h3>Directive 1</h3>' +
'<div ng-repeat="item in data.items">' +
'<input type="text" ng-model="item.name"/>' +
'</div>',
link: function(scope, elem, attr) {
scope.data = dataService;
}
};
});
app.directive('secondDirective', function(dataService){
return {
restrict: 'E',
template: '<h3>Directive 2</h3>' +
'<div ng-repeat="item in data.items">' +
'<input type="text" ng-model="item.name"/>' +
'</div>',
link: function(scope, elem, attr) {
scope.data = dataService;
}
};
});
app.factory('dataService', [function(){
return { items: [] };
}]);
The Demo
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, dataService) {
$scope.name = 'World';
//set up the items.
angular.copy([ { name: 'test'} , { name: 'foo' } ], dataService.items);
});
app.directive('firstDirective', function(dataService){
return {
restrict: 'E',
template: '<h3>Directive 1</h3>' +
'<div ng-repeat="item in data.items">' +
'<input type="text" ng-model="item.name"/>' +
'</div>',
link: function(scope, elem, attr) {
scope.data = dataService;
}
};
});
app.directive('secondDirective', function(dataService){
return {
restrict: 'E',
template: '<h3>Directive 2</h3>' +
'<div ng-repeat="item in data.items">' +
'<input type="text" ng-model="item.name"/>' +
'</div>',
link: function(scope, elem, attr) {
scope.data = dataService;
}
};
});
app.factory('dataService', [function(){
return { items: [] };
}]);
<script src="//unpkg.com/angular/angular.js"></script>
<body ng-app="myApp" ng-controller="myCtrl">
<first-directive></first-directive>
<second-directive></second-directive>
</body>

how to add dynamic element(template) in angular

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;
}
}
};
})

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: '='
}

Resources