How to override angular ui bootstrap datepicker - angularjs

I want to add new type class button in my datepicker.
Example:
Button blue colour for range date from Jan 8, 2014 until Jan 18, 2014
or, button red colour for date Feb 2, 2014.
I already try to ovveride datepicker directive, but it doesn't work. Here my codes:
angular.module('App').directive('NewDatepickerPopup',function(){
return{
restrict: 'EA',
replace: true,
require: ['datepicker'],
templateUrl: 'template/datepicker/datepicker.html',
controller: function($scope){
console.log('controller NewDatepickerPopup');
},
link: function(scope, element, attrs, requiredControllers){
console.log('requiredControllers',requiredControllers);
console.log('link NewDatepickerPopup');
element.on('click',function(){
console.log('on click nya disini');
});
}
};
});
angular.module("template/datepicker/datepicker.html", []).run(["$templateCache",
function($templateCache) {
$templateCache.put("template/datepicker/datepicker.html",
"<table class=\"zor-datepicker\" >\n" +
" <thead>\n" +
" <tr>\n" +
" <th><button type=\"button\" class=\"btn btn-cal btn-sm pull-left\" ng-click=\"move(-1)\"><i class=\"fa fa-angle-left fa-lg\"></i></button></th>\n" +
" <th colspan=\"{{rows[0].length - 2 + showWeekNumbers}}\"><button type=\"button\" class=\"btn btn-cal btn-sm btn-block\" ng-click=\"toggleMode()\">{{title}}</button></th>\n" +
" <th><button type=\"button\" class=\"btn btn-cal btn-sm pull-right\" ng-click=\"move(1)\"><i class=\"fa fa-angle-right fa-lg\"></i></button></th>\n" +
" </tr>\n" +
" <tr ng-show=\"labels.length > 0\" class=\"h6\">\n" +
" <th ng-show=\"false\" class=\"text-center ng-hide\">#</th>\n" +
" <th ng-repeat=\"label in labels\" class=\"text-center\">{{label}}</th>\n" +
" </tr>\n" +
" </thead>\n" +
" <tbody>\n" +
" <tr ng-repeat=\"row in rows\">\n" +
" <td ng-show=\"false\" class=\"text-center ng-hide\"><em>{{ getWeekNumber(row) }}</em></td>\n" +
" <td ng-repeat=\"dt in row\" class=\"text-center\">\n" +
" <button type=\"button\" style=\"width:100%;\" class=\"btn btn-default btn-sm\" ng-class=\"{'btn-info': dt.selected}\" ng-click=\"select(dt.date)\" ng-disabled=\"dt.disabled\"><span ng-class=\"{'text-muted': dt.secondary}\">{{dt.label}}</span></button>\n" +
" </td>\n" +
" </tr>\n" +
" </tbody>\n" +
"</table>\n" +
"");
}
]);
<input id="ph" ng-click="openCheckin($event)" name="in" type="text" class="form-control search home" new-datepicker-popup datepicker-popup="{{format}}" ng-model="check_in" ng-change="changeCheckinDate()" is-open="openedCheckin" min="minCheckInDate" ng-required="false" show-weeks="false" show-button-bar="false" close-text="Close" placeholder=""/>
Anybody could help me?
Thank you so much
*Sorry my english so bad.

Take a look on this post: https://github.com/angular-ui/bootstrap/issues/743
You could use decorator in the config phase to override the templateUrl

Related

How To add ng-model dynamically inside angular.forEach

This is what I append to my modal on load, and it's working fine, except the checkbox row.
//$scope.items is retrieved by an api, and looks something like this.
$scope.items[0] = ['delivered' : true, 'status': 'delivered']
$scope.items[1] = ['delivered': false, 'status': 'pending']
angular.element('.row-modal').empty();
request.success(function(response) {
$scope.paymentTransactionServices = response;
angular.forEach($scope.paymentTransactionServices, function(value, index) {
var deliveredBy = value.deliveredBy ? value.deliveredBy.email : null;
angular.element('#table-services').append('<tr class = "row-modal">' +
'<td>' + value.title + '</td>' +
'<td>' + deliveredBy + '</td>' +
'<td>' + '<label class="checkbox-inline">' +
' <input type="checkbox" ng-model=' + $scope.paymentTransactionServices[index].delivered + ' ng-change="print()" />' + value.status + '</label> </td>' +
'<td>' + value.delivery_date + '</td>' +
'</tr>'
);
})
What I expect is that if "delivered" is false, the checkbox should notbe checked and if true then it should be checked. And on click, i want to fire a function but it's not working...
You should never alter the dom like that, as this may result in unexpected errors and memory leaks in you application.
You should always use directives & components for this kind of stuff.
What you should do, in your template, is:
<table id="table-services">
<tr>
<th>Title</th>
<th>Delivered by</th>
<th>Status</th>
<th>Delivery date</th>
</tr>
<tr ng-repeat="service in paymentTransactionServices" class="row-modal">
<td>{{ service.title }}</td>
<td>{{ service.deliveredBy.email || null }}</td>
<td>
<label class="checkbox-inline">
<input type="checkbox" ng-model="service.delivered" ng-change="print()" />
{{ service.status }}
</label>
</td>
<td>{{ service.delivery_date | date }}</td>
</tr>
</table>
If you need to check a checkbox, you must add checked attribute to your HTML element. In the above case, there is no checked attributed on that element.
On the other hand, I have a doubt if click event exists on checkbox. Kindly use change instead.
Check if the below works
input type="checkbox" checked={{value.delivered}} (change)=print()

How to reduce watchers in AngularJS 1.3 - performance issue

An internal web software that is being used by a warehouse. It contains a table of orders with items that need to be scanned and prepared for delivery.
It has 3 sorting options, 12 main and secondary filters. The table was created by ng-repeat, and there are lots of references for scope variables.
It contains one main array with about 2000 objects inside, and also has a few more object helpers as well - some are small and some are big.
The main array needs to be refreshed by AJAX every minute to refresh the table, since there are several people who use it simultaneously.
Array example:
[0:{Barcode:"1234", Description:"Hisense 50 Inch Quad Core UHD 4K Smart Led TV", Docbal: 0, Docdate:"17/10/2017", Docnum:111111, FastOrder:0, GrpCode:111, NotInStock:true, Notes:"Hello", OnHand:0, OpenQty:1, OrderNumber:1736604, PartOfNotInStock:true, Total:2123, cntOrdersToDemand:6, commited:true, isMultiple:false, multipleChecked:true, relevantStock:0, scanned:0, shelf:null}]
Every scan executes a series of events that contain lots of data searching and updating in the clients objects.
almost all functions and variables are in the scope and being called and used by ng-click etc.
At the beginning there weren't performance problems since the array was pretty small, but now it got bigger and I saw that there are up to 60,000 watchers (!) in the program.
Is there a possibility to maintain the current structure with a few changes?
The table tr creation:
<tr ng-repeat="docs in itemsData | filter: searchText | filter: filterTable(currentFilter) : true | orderBy: orderType" ng-class="{'notinstock':docs.NotInStock,'text-center': true, 'marked': docs.OpenQty==docs.scanned}" ng-show="( (multipleDocs==docs.isMultiple) || (multipleDocs=='all') ) && ((docs.Docbal>0)!=noDebt) && ((docs.PartOfNotInStock>0)!=notInStock) && ((docs.FastOrder==0) != fastOrder)" docnum="{{docs.Docnum}}" orderNumber="{{docs.OrderNumber}}" barcode="{{docs.Barcode}}">
<td>
<div class="copyDiv" ng-show="(!docs.FastOrder)">
<i ng-click="searchItems(docs.Docnum, 'doc')" title="לחיצה לחיפוש / חזרה מחיפוש" ng-class="{'fa fa-search-minus': searchOnDoc==true, 'fa fa-search-plus':searchOnDoc==false}" class="searchIcon itemClick" aria-hidden="true"></i>
<span title="לחיצה להעתקה" ng-click="clipboardCopyDoc('doc'+$index)" id="copyClickDoc{{'doc'+$index}}" class="clipboard itemClick" ngclipboard data-clipboard-text="{{docs.Docnum}}"> {{docs.Docnum}}</span>
</div>
<div class="docDate" ng-show="(!docs.FastOrder)">{{docs.Docdate}}</div>
<span ng-switch on="docs.shipping" ng-click="openInvoice(docs.Docnum)" title="{{ docs.FastOrder ? '' : 'לחיצה לצפייה בפרטי חשבונית' }}" ng-class="{'itemClick' : !docs.FastOrder}">
<span ng-switch-when="shipping" class="label label-by">Chita</span>
<span ng-switch-when="shipping_ev" class="label label-purplew">Buzzr</span>
<span ng-switch-when="pickup" class="label label-bw">איסוף</span>
<span ng-switch-when="boxit" class="label label-pinkw">Boxit</span>
<span ng-switch-when="postil" class="label label-rw">דואר</span>
<span ng-switch-default class="label label-brownw">לא צוין</span>
</span>
<span ng-show="docs.FastOrder" ng-click="cancelFastOrderSure(docs.OrderNumber)" class="label label-danger itemClick cancelOrderBt" title="לחיצה לביטול ההזמנה המהירה"><i class="fa fa-fast-backward"></i> לחץ כדי להחזיר למכירות</span>
</td>
<td>
<div class="copyDiv">
<i ng-click="searchItems(docs.OrderNumber, 'doc')" title="לחיצה לחיפוש / חזרה מחיפוש" ng-class="{'fa fa-search-minus': searchOnDoc==true, 'fa fa-search-plus':searchOnDoc==false}" class="searchIcon itemClick" aria-hidden="true"></i>
<span title="לחיצה להעתקה" ng-click="clipboardCopyDoc('ord'+$index)" id="copyClickDoc{{'ord'+$index}}" class="clipboard itemClick" ngclipboard data-clipboard-text="{{docs.OrderNumber}}"> {{docs.OrderNumber}}</span>
</div>
<div class="docDate" ng-show="(docs.FastOrder)">{{docs.Docdate}}</div>
<span class="itemClick" ng-click="openOrder(docs.OrderNumber)" title="לחיצה לצפייה בפרטי ההזמנה">
<span ng-show="docs.FastOrder" class="label label-danger"><i class="fa fa-fast-backward"></i> הזמנה מהירה</span>
<span ng-show="!docs.FastOrder" class="label label-default">הזמנה רגילה</span>
</span>
</td>
<td>
<div class="copyDiv">
<i ng-click="searchItems(docs.Barcode, 'bar')" title="לחיצה לחיפוש / חזרה מחיפוש" ng-class="{'fa fa-search-minus': searchOnBar ==true, 'fa fa-search-plus':searchOnBar ==false}" class="searchIcon itemClick" aria-hidden="true"></i>
<span title="לחיצה להעתקה" ng-click="clipboardCopyBar($index)" id = "copyClickBar{{$index}}"class = "clipboard itemClick" ngclipboard data-clipboard-text="{{docs.Barcode}}"> {{docs.Barcode}}</span>
</div>
</td>
<td ng-bind-html="renderDoc(docs)"></td>
<td class="itemClick" title="לחיצה להצגת סיריאלים זמינים" ng-click="peekAtSerials(docs.Barcode,docs.Docnum,docs.OrderNumber)">{{docs.scanned}}/{{docs.OpenQty}}</td>
<td class="notes" ng-bind-html="renderHtml(docs.Notes)"></td>
<td>{{docs.cntOrdersToDemand}}/{{docs.relevantStock}}</td>
<td>{{ getShelf(docs); }}</td>
<td class="balance" ng-bind-html="renderHtml(getBal(docs.Docbal))"></td>
</tr>
The program needs to work also on a tablet, so this architecture of burdening the client with so much computing concerns - using so much memory and resources - makes me wonder if I need to change the app to be completely server side based.
I already tried to create the table using JavaScript only, and compile it. It reduced the watchers to 1600, but it took lots of memory and CPU, and every time the table was refreshed, the program got stuck for a few seconds. also it means that on every filter it needs to be created again. Is there a better way to do this?
what I did:
HTML:
<tbody id="tBody" compile="tr" ng-show="trNow"></tbody>
<tbody id="tBody" compile="tr2" ng-show="!trNow"></tbody>
compile directive:
myApp.directive('compile', ['$compile', function ($compile) {
return function(scope, element, attrs) {
scope.$watch(
function(scope) {
return scope.$eval(attrs.compile);
},
function(value) {
element.html(value);
$compile(element.contents())(scope);
}
);
};
}]);
functions that create the table:
function makeTable(){
makeTr(function(tr){
switch($scope.trNow){
case true: //tr
$scope.tr2 = tr;
$scope.trNow = false;
$scope.tr = "";
break;
case false: //tr2
$scope.tr = tr;
$scope.trNow = true;
$scope.tr2 = "";
break;
}
}
);
}
async function makeTr(callBack){
var tr = "";
for (var i=0; i<itemsDataView.length; i++){
var titleText= itemsDataView[i].FastOrder ? '' : 'לחיצה לצפייה בפרטי חשבונית';
var trClassNIS = itemsDataView[i].NotInStock ? 'notinstock' : '';
var trClassMark = (itemsDataView[i].OpenQty == itemsDataView[i].scanned) ? 'marked' : '';
var trClass = itemsDataView[i].NotInStock ? 'notinstock' : '';
var trClass = itemsDataView[i].NotInStock ? 'notinstock' : '';
var trClass = itemsDataView[i].NotInStock ? 'notinstock' : '';
var showSearch = $scope.searchOnDoc==true ? 'fa fa-search-minus' : 'fa fa-search-plus';
var showNoFast = !itemsDataView[i].FastOrder ? '<div class="copyDiv">'+
'<i ng-click="searchItems('+itemsDataView[i].Docnum+',\'doc\')" title="לחיצה לחיפוש / חזרה מחיפוש" class="'+showSearch+' searchIcon itemClick" aria-hidden="true"></i>'+
'<span title="לחיצה להעתקה" ng-click="clipboardCopyDoc(\'doc\'+'+i+')" id="copyClickDodoc'+i+'" class="clipboard itemClick" ngclipboard data-clipboard-text="'+ itemsDataView[i].Docnum+'"> '+itemsDataView[i].Docnum+'</span>'+
'</div><div class="docDate">'+itemsDataView[i].Docdate+'</div>' : '';
var switchShippingClass = !itemsDataView[i].FastOrder ? 'itemClick' : '';
var switchShipping;
switch(itemsDataView[i].shipping){
case "shipping":
switchShipping = '<span class="label label-by">Chita</span>';
break;
case "shipping_ev":
switchShipping = '<span class="label label-purplew">Buzzr</span>';
break;
case "pickup":
switchShipping ='<span class="label label-bw">איסוף</span>';
break;
case "boxit":
switchShipping ='<span class="label label-pinkw">Boxit</span>';
break;
case "postil":
switchShipping ='<span class="label label-rw">דואר</span>';
break;
default:
switchShipping ='<span class="label label-brownw">לא צוין</span>';
}
var fastOrderSpan = itemsDataView[i].FastOrder ? '<br><span ng-click="cancelFastOrderSure('+itemsDataView[i].OrderNumber+')" class="label label-danger itemClick cancelOrderBt" title="לחיצה לביטול ההזמנה המהירה"><i class="fa fa-fast-backward"></i> לחץ לביטול הזמנה מהירה</span>' : "";
var fastOrderDiv = itemsDataView[i].FastOrder ? '<div class="docDate">'+itemsDataView[i].Docdate+'</div>' : "";
var fastOrdeSpanYesNo = itemsDataView[i].FastOrder ? '<span class="label label-danger"><i class="fa fa-fast-backward"></i> הזמנה מהירה</span>' : '<span class="label label-default">הזמנה רגילה</span>';
tr+='<tr class="'+trClassNIS +' text-center '+trClassMark+'" docnum="'+ itemsDataView[i].Docnum+'" orderNumber="'+ itemsDataView[i].OrderNumber+' "barcode="'+ itemsDataView[i].Barcode+'">'+
'<td>'+showNoFast+
'<span ng-click="openInvoice('+itemsDataView[i].Docnum+')" title="'+ titleText +'" class="'+switchShippingClass+'">'+
switchShipping+
'</span>'+
fastOrderSpan+
'</td>'+
'<td>'+
'<div class="copyDiv">'+
'<i ng-click="searchItems('+itemsDataView[i].OrderNumber+', \'doc\')" title="לחיצה לחיפוש / חזרה מחיפוש" class="'+showSearch+' searchIcon itemClick" aria-hidden="true"></i> '+
'<span title="לחיצה להעתקה" ng-click="clipboardCopyDoc(\'ord\'+'+i+')" id="copyClickDocord'+i+'" class="clipboard itemClick" ngclipboard data-clipboard-text="'+itemsDataView[i].OrderNumber+'"> '+itemsDataView[i].OrderNumber+'</span>'+
'</div>'+
fastOrderDiv+
'<span class="itemClick" ng-click="openOrder('+itemsDataView[i].OrderNumber+')" title="לחיצה לצפייה בפרטי ההזמנה">'+
fastOrdeSpanYesNo+
'</span>'+
'</td>'+
'<td>'+
'<div class="copyDiv">'+
'<i ng-click="searchItems('+itemsDataView[i].Barcode+', \'bar\')" title="לחיצה לחיפוש / חזרה מחיפוש" class="'+showSearch+' searchIcon itemClick" aria-hidden="true"></i> '+
'<span title="לחיצה להעתקה" ng-click="clipboardCopyBar('+i+')" id = "copyClickBar{{'+i+'}}" class = "clipboard itemClick" ngclipboard data-clipboard-text="'+itemsDataView[i].Barcode+'"> '+itemsDataView[i].Barcode+'</span>'+
'</div>'+
'</td>'+
'<td>'+$scope.renderDoc(itemsDataView[i])+'</td>'+
'<td class="itemClick" title="לחיצה להצגת סיריאלים זמינים" ng-click="peekAtSerials('+itemsDataView[i].Barcode+', '+itemsDataView[i].Docnum+','+itemsDataView[i].OrderNumber+')">'+itemsDataView[i].scanned+'/'+itemsDataView[i].OpenQty+'</td>'+
'<td class="notes">'+$scope.renderHtml(itemsDataView[i].Notes)+'</td>'+
'<td>'+itemsDataView[i].cntOrdersToDemand+'/'+ itemsDataView[i].relevantStock+'</td>'+
'<td>'+$scope.getShelf(itemsDataView[i])+'</td>'+
'<td class="balance">'+$scope.renderHtml($scope.getBal(itemsDataView[i].Docbal))+'</td>'+
'</tr>';
}
callBack (tr);
}

Conditional ng-show

Is there any way to put a condition in the following:
<h3 ng-show="ctrl.loggedIn">
{{ctrl.loggedInUser.FirstName + " " + ctrl.loggedInUser.LastName + " is logged in."}}
</h3>
that is if the ctrl.loggedInUser.FirstName is undefined or null then it wouldn't print.
Click here to visit the project on github.
yes you can. use ng-if to add conditions in DOM
<h3 ng-show="ctrl.loggedIn" ng-if="ctrl.loggedInUser.FirstName">
{{ctrl.loggedInUser.FirstName + " " + ctrl.loggedInUser.LastName + " is logged in."}}
</h3>
h3 will only show if ctrl.loggedInUser.FirstName have some value
<h3 ng-show="ctrl.loggedIn && ( ctrl.loggedInUser.FirstName!=null || (ctrl.loggedInUser.FirstName!='undefined')")>
{{ctrl.loggedInUser.FirstName + " " + ctrl.loggedInUser.LastName + " is logged in."}}
</h3>
you can also do like
<h3 ng-hide="!ctrl.loggedIn && (ctrl.loggedInUser.FirstName==null || (ctrl.loggedInUser.FirstName=='undefined')")>
{{ctrl.loggedInUser.FirstName + " " + ctrl.loggedInUser.LastName + " is logged in."}}
</h3>
You can use ng-show
<h3 ng-show="ctrl.loggedInUser.FirstName!=undefined || ctrl.loggedInUser.FirstName!=null">
{{ctrl.loggedInUser.FirstName + " " + ctrl.loggedInUser.LastName + " is logged in."}}
</h3>
<div ng-switch on="ctrl.loggedInUser.FirstName == null || ctrl.loggedInUser.FirstName == undefined || ctrl.loggedInUser.FirstName == ''">
<h3 ng-switch-when="true">Please log in.</h3>
<h3 ng-switch-when="false">{{ctrl.loggedInUser.FirstName + " " + ctrl.loggedInUser.LastName + " is logged in."}}</h3>
</div>
this worked for me.
thanks all for the ideas.

Buttons added to a table generated with AngularJS Datatables are not executing functions in the current escope

EDIT
I tried to update the function actionButtons():
function actionButtons(data, type, full, meta) {
vm.project[data.id] = data;
var html = '<button class="btn btn-info btn-xs" ng-click="project.editProject(' + data.id + ')">' +
' <i class="fa fa-edit"></i>' +
'</button> ' +
'<button class="btn btn-danger btn-xs" ng-click="project.deleteProject(' + data.id + ')">' +
' <i class="fa fa-trash-o"></i>' +
'</button>';
el = $compile(html)($scope);
return el;
}
Now it's rendering [Object][Object] instead of the HTML buttons. At least it produced a different result.
ORIGINAL POST
I have a table built with AngularJS Datatables as it follows:
HTML
<div ng-controller="ProjectCtrl as project">
<table datatable="" dt-options="project.standardOptions" dt-columns="project.standardColumns" dt-instance="project.dtInstance" class="table table-condensed table-striped table-bordered table-hover" width="100%">
<thead>
<tr>
<th data-hide="phone">ID</th>
<th data-class="expand"> Processo</th>
<th data-class="expand"> Objeto</th>
<th data-hide="phone"><i class="fa fa-fw fa-map-marker txt-color-blue hidden-md hidden-sm hidden-xs"></i> UF</th>
<th>Região</th>
<th data-hide="phone,tablet"> Macrossegmento</th>
<th data-hide="expand"> </th>
</tr>
</thead>
</table>
</div>
JavaScript/Controller
.controller('ProjectCtrl', function($scope){
vm.standardOptions = DTOptionsBuilder
// TODO: Get the data below from a service
.fromSource('/api/BasesDados/Concessoes/concessoes.php')
.withOption('scrollX', '100%')
.withDOM("<'dt-toolbar'<'col-xs-12 col-sm-6'f><'col-sm-6 col-xs-12 hidden-xs'l>r>" +
"t" +
"<'dt-toolbar-footer'<'col-sm-6 col-xs-12 hidden-xs'i><'col-xs-12 col-sm-6'p>>")
.withBootstrap()
.withButtons([
{extend: 'colvis', text: 'View'},
{extend: 'copy', text: 'Copy'},
{extend: 'print', text: 'Print'},
{extend: 'excel', text: 'MS Excel'},
{
text: 'Add project',
key: '1',
action: function (e, dt, node, config) {
$scope.addProject();
}
}
]);
// Rendered columns. ID is not shown
vm.standardColumns = [
DTColumnBuilder.newColumn('id').notVisible(),
DTColumnBuilder.newColumn('processo'),
DTColumnBuilder.newColumn('objeto'),
DTColumnBuilder.newColumn('uf'),
DTColumnBuilder.newColumn('regiao'),
DTColumnBuilder.newColumn('macro'),
DTColumnBuilder.newColumn(null).withTitle('Ações').notSortable().renderWith(actionButtons)
];
// Action buttons added to the last column: to edit and to delete rows
function actionButtons(data, type, full, meta) {
vm.project[data.id] = data;
return '<button class="btn btn-info btn-xs" ng-click="project.editProject(' + data.id + ')">' +
' <i class="fa fa-edit"></i>' +
'</button> ' +
'<button class="btn btn-danger btn-xs" ng-click="project.deleteProject(' + data.id + ')">' +
' <i class="fa fa-trash-o"></i>' +
'</button>';
}
});
The action buttons added through the function actionButtons() to the last column in the table receive an action each one: delete and edit.
However, the functions don't seem to respond to the click on those action buttons:
// Edit a project
$scope.editProject= function(projetoId){
console.log(projetoId);
}
// Delete a project
$scope.deleteProject= function(projetoId){
console.log(projetoId);
}
Note that the buttons receive the parameters:
<button ng-click="project.editProject(5026)">Editar</button>
It must be a conceptual misunderstanding on AngularJS scopes. What am I doing wrong in this case?
The code doesn't raise any error as I can notice by the output on the console of the browser (Google Chrome 56., Mozilla Firefox 50., MSIE 11.*).
My code is running on IIS 8.5 (it's irrelevant, I guess).
Found the solution.
Accordin to the AngularJS Datatables documentation, the following function compiles each row:
function createdRow(row, data, dataIndex) {
$compile(angular.element(row).contents())($scope);
}
Then you have to add it to the options:
vm.standardOptions = DTOptionsBuilder
.fromSource(urlToTheData)
.withOption('createdRow', createdRow) // Here, I recompile the table's rows
.withOption('scrollX', '100%')
...
I also had to remove the controller alias from ng-click:
From this <button ng-click="project.editProject(5026)">Edit</button>
To this <button ng-click="editProject(5026)">Edit</button>.
Thank to #AsielLealCeldeiro I added a $compile (searched the docs for it) and thanks to #Yaser I plyed with the compile service.
Thank you, StackOverflow community!

Appending Angucomplete dynamically resets input

I have a UI in which I'm adding angucomplete as dynamic html. I have a directive that that compiles the html on add like this :
.directive('dynamic', function ($compile) {
return {
restrict: 'A',
replace: true,
link: function (scope, ele, attrs) {
scope.$watch(attrs.dynamic, function (html) {
console.log('dynamic watch');
ele.html(html);
$compile(ele.contents())(scope);
});
}
};
})
Now I have an add button which appends angucompletes text-boxes to the existing html which is in directive 'dynamic'. When I add an angucomplete all my previous selected values also get cleared. I don't understand why. I tried debugging angucomplete-alt.js but couldn't find the cause.
I have also used ng-tagsinput in the similar scenario and works great, when I add a new row the previous tags-input doesn't loose its selected value.
function recommendationHtml(recommedCount) {
var men = 'men';
var women = 'women';
var tblRecommend = ' <table id="tblid'+recommedCount+'" style="padding:5px;border-bottom:solid 1px;"> '
+ ' <tr> '
+ ' <td class="td-recommendation"><i class="icon fa-inr fa-2x"></i> '
+ ' </td> '
+ ' <td> '
+ '<div class="item range range-positive"> '
+ '<label id="spanprice_' + recommedCount + '" name="spanprice_' + recommedCount + '">1000</label> '
+ '<input id="slider_' + recommedCount + '" type="range" step="500" name="slider_' + recommedCount + '" min="1000" max="50000" value="1000" '
+ ' onchange="angular.element(document.querySelector(\'#spanprice_0\')).val(this.value);"/> '
+ ' </div> '
+ ' </td> '
+ ' </tr> '
+ ' <tr> '
+ ' <td class="td-recommendation"><i class="icon ion-bag fa-2x"></i> '
+ ' </td> '
+ ' <td> '
+ ' <tags-input ng-model="vendors' + recommedCount + '" id="vendors' + recommedCount + '" '
+ ' display-property="name" '
+ ' key-property="id" '
+ ' on-tag-added="storeTagAdded($tag)" '
+ ' on-tag-removing="storeTagRemoved($tag)" '
+ ' max-tags="1" '
+ ' placeholder="store"> '
+ ' <auto-complete source="loadVendors($query)"></auto-complete> '
+ ' </tags-input> '
+ ' </td> '
+ ' </tr> '
+ ' <tr> '
+ ' <td class="td-recommendation"><i class="icon ion-bag fa-2x"></i></td> '
+ ' <td> '
+ '<div angucomplete-alt id="vendor' + recommedCount + '" placeholder="Search Store" '
+ 'pause="300" selected-object="selectedVendorPost" local-data="vendorData"'
+ ' search-fields="name" title-field="name" description-field="email"'
+ ' image-field="image" minlength="1" remote-url-data-field="name"'
+ ' input-class="form-control form-control-small"'
+ ' match-class="highlight" style="border-bottom: 1px solid;"'
+ ' ng-keydown="removedVendorPost($event,' + recommedCount + ')" >'
+ '</div>'
+ ' </td> '
+ ' </tr> '
+ ' <tr> '
+ ' <td class="td-recommendation"><i class="icon ion-tshirt-outline fa-2x"></i></td> '
+ ' <td> '
+ '<div angucomplete-alt id="apparel_' + recommedCount + '" placeholder="Search apparel" '
+ 'pause="300" selected-object="selectedApparel" local-data="apparelData"'
+ ' search-fields="tagname" title-field="tagname" description-field=""'
+ ' image-field="" minlength="1" remote-url-data-field=""'
+ ' input-class="form-control form-control-small"'
+ ' match-class="highlight" style="border-bottom: 1px solid;"'
+ ' ng-keydown="removedApparel($event,' + recommedCount + ')" >'
//+ ' onkeydown="javascript:console.log(event:' + 'event.which' + 'value:' + ' this.value' + 'index:' + recommedCount + ');"'
+ '</div>'
+ ' </td> '
+ ' </tr> '
+ ' </table>';
return tblRecommend;
};
$scope.addRecommend = function() {
$scope.html = $scope.html + recommendationHtml($scope.recommedCount);
$scope.recommedCount = $scope.recommedCount + 1;
//$compile(recommendationHtml(0).contents())($scope);
};
.directive('dynamic', function($compile) {
return {
restrict: 'A',
replace: true,
link: function(scope, ele, attrs) {
scope.$watch(attrs.dynamic, function(html) {
console.log('dynamic watch');
ele.html(html);
$compile(ele.contents())(scope);
});
}
};
})
<div dynamic="html"></div>

Resources