Angular Directive in ng-repeat generating randomly uncorrect DOM - angularjs

Hello i have a directive like this in my ASP MVC application + Kendo Upload (doesn't matter)
<div ng-repeat="dp in dealerphotos" class="imgbox">
<div ng-if="dp.DealerPhotoId != 0">
<div class="img-wrapper">
<a data-lightbox="{{ dp.DealerId }}{{ dp.PhotoId }}{{ dp.FileName }}" data-title="{{ dp.FileName }}" href="~/Upload/{{ dp.DealerId }}/{{ dp.PhotoId }}/{{ dp.FileName }}">
<img ng-src="~/Image/Resized?size={{ resize }}&dealerId={{ dp.DealerId }}&photoId={{ dp.PhotoId }}&fileName={{ dp.FileName }}" alt="" class="uploaded" center-preview />
</a>
</div>
<div class="btnblock">
<button ng-click="changePhoto(dp.DealerPhotoId, dp.PhotoId, $index)" title="#Resources.Strings.ButtonChange"><span class="icon pencil"></span></button>
<button ng-click="removePhoto(dp.DealerPhotoId)" title="#Resources.Strings.ButtonRemove"><span class="icon trash"></span></button>
</div>
</div>
<div ng-show="dp.DealerPhotoId == 0" ng-attr-class="{{ (dp.IsFirstMandatory || dp.IsFirstMandatoryIfInstalled) ? 'mandatory' : '' }}">
<input name="files"
type="file"
kendo-upload
k-multiple="false"
k-async="{ saveUrl: '/Steps/Save', autoUpload: true }"
k-select="onSelect"
k-error="onError"
k-success="onSuccess"
k-upload="onUpload"
title="#Resources.Strings.ButtonAdd" />
<div class="mandatory-marker">
<p ng-if="dp.IsFirstMandatory">#Resources.Strings.StepMandatory</p>
<p ng-if="!dp.IsFirstMandatory && dp.IsFirstMandatoryIfInstalled" class="installed">#Resources.Strings.StepMandatoryIfInstalled</p>
</div>
</div>
</div>
With .js code:
//IFFE
(function () {
var app = angular.module("app");
app.directive('tripleUploadDirective', ['$http', function () {
var controller = [
'$scope', '$http', function ($scope, $http) {
$scope.dealerPhotoId = null;
$scope.removePhoto = function (id) {
swal({
title: "", text: localization.StepRemoveConfirm, type: "warning",
showCancelButton: true,
confirmButtonColor: "#DD6B55",
confirmButtonText: localization.AlertYesRemove,
closeOnConfirm: true,
animation: "slide-from-top"
}, function () {
$http.post("/Steps/Remove", { dealerPhotoId: id }).then(function (data) {
for (var i = 0; i < data.data.length; i++) {
if (i == 0 && data.data[i].DealerPhotoId == 0) {
if ($scope.mandatory)
data.data[i].IsFirstMandatory = true;
if ($scope.mandatoryifinstalled)
data.data[i].IsFirstMandatoryIfInstalled = true;
}
}
$scope.dealerphotos = data.data;
});
});
};
$scope.changePhoto = function (dealerPhotoId, id, index) {
swal({
title: "", text: localization.StepChangeConfirm, type: "warning",
showCancelButton: true,
confirmButtonColor: "#DD6B55",
confirmButtonText: localization.AlertYesChange,
closeOnConfirm: true,
animation: "slide-from-top"
}, function () {
$scope.dealerPhotoId = dealerPhotoId;
var uploadinput = angular.element("#div_" + id + " input[name=files]")[index];
angular.element(uploadinput).click();
});
};
$scope.onSelect = function (e) {
$.each(e.files, function (index, value) {
var ok = value.extension.toLowerCase() == ".jpg" || value.extension == ".jpeg";
if (!ok) {
e.preventDefault();
swal({ title: "", text: localization.StepValidateExtension, type: "error", confirmButtonText: localization.AlertOK, animation: "slide-from-top" });
}
});
};
$scope.onError = function (e) {
swal({ title: "", text: e.XMLHttpRequest.response, type: "error", confirmButtonText: localization.AlertOK, animation: "slide-from-top" });
$scope.$apply();
};
$scope.onSuccess = function (e) {
if (e.response != null) {
for (var i = 0; i < e.response.length; i++) {
if (i == 0 && e.response[i].DealerPhotoId == 0) {
if ($scope.mandatory)
e.response[i].IsFirstMandatory = true;
if ($scope.mandatoryifinstalled)
e.response[i].IsFirstMandatoryIfInstalled = true;
}
}
$scope.dealerphotos = e.response;
$scope.$apply();
}
};
$scope.onUpload = function (e) {
e.data = { photoId: $scope.photoid, dealerPhotoId: $scope.dealerPhotoId };
$scope.dealerPhotoId = null;
};
}];
return {
restrict: 'EAC',
scope: {
dealerphotos: '=dealerphotos',
photoid: '=photoid',
mandatory: '=mandatory',
mandatoryifinstalled: '=mandatoryifinstalled',
resize: '=resize'
},
replace: true,
templateUrl: '/Directives/TripleUpload',
controller: controller
};
}]);
})();
This directive is used in ng-repeat:
<div ng-repeat="step in matrixCtrl.allSteps" class="m-step">
<div class="step-title">{{step.stepIndex}} | {{ step.Name }}</div>
<div triple-upload-directive dealerphotos="step.dealerPhotos" photoid="step.PhotoId" resize="170" mandatory="step.IsMandatory" mandatoryifinstalled="step.IsMandatoryIfInstalled" class="img-uploder {{ step.IsMandatory ? 'mandatory' : '' }}"></div>
</div>
I am setting allSteps in matrixCtrl in success() callback of $http.get().
My problem is the very strange behaviour of ng-repeat.. sometimes (very randomly), my DOM is not generated correctly. (all directives are rendered only in last ng-repeat iteration), in other iterations there are only titles.
Incorrect rendering image:

Related

How to access multiple services in angularjs controller

In an aspnetboilerplate .cshtml page, we have
div ng-controller="app.views.automate as vm"
, this angular controller access the automateService from asp.net mvc controller.
inside that div , we are loading partial view from another .cshtml file, here it should have a different service(excelService) from the Asp.net mvc controller. How to achieve it.
Angular.js
(function () {
var controllerId = 'app.views.automate';
angular.module('app').controller(controllerId, [
'$scope', 'abp.services.app.automate', function ($scope, automateService) {
var vm = this;
//Automate logic...
//Model
vm.currentStep = 1;
vm.steps = [
{
step: 1,
name: "First step",
template: "/App/Main/views/automate/step1.cshtml",
controller: 'app.views.excel as vm'
},
{
step: 2,
name: "Second step",
template: "/App/Main/views/automate/step2.cshtml"
},
{
step: 3,
name: "Third step",
template: "/App/Main/views/automate/step3.cshtml",
controller: 'app.views.capacity as vm'
}
];
//Functions
vm.gotoStep = function (newStep) {
vm.currentStep = newStep;
//$scope.ParseExcel();
}
vm.getStepTemplate = function () {
for (var i = 0; i < vm.steps.length; i++) {
if (vm.currentStep == vm.steps[i].step) {
return vm.steps[i].template;
}
}
}
vm.save = function () {
//todo: save data...
//vm.location['abq'].center
//alert(vm.location.abq.center);
// vm.enterCapacity(vm.location);
}
vm.enterCapacity = function () {
// alert(vm.capacity.locations[0].center);
automateService.calculateCapacity(vm.capacity).then(function () {
abp.notify.info(app.localize('SavedSuccessfully'));
});
}
$scope.SelectedFileForUpload = null; //initially make it null
$scope.BindData = null;
$scope.showLoader = false;
$scope.IsVisible = false;
$scope.UploadFiles = function (files) {
$scope.$apply(function () {
$scope.Message = '';
$scope.SelectedFileForUpload = files[0];
});
}
vm.capacity = {
locations: [
{ city: "abq", center: 0, housing: 0 },
{ city: "han", center: 0, housing: 0 },
{ city: "udh", center: 0, housing: 0 },
{ city: "dhn", center: 0, housing: 0 },
{ city: "spp", center: 0, housing: 0 },
{ city: "rt", center: 0, housing: 0 },
{ city: "has", center: 0, housing: 0 },
{ city: "jed", center: 0, housing: 0 },
{ city: "ry", center: 0, housing: 0 },
{ city: "yan", center: 0, housing: 0 },
{ city: "tan", center: 0, housing: 0 },
{ city: "itq", center: 0, housing: 0 },
{ city: "abq", center: 0, housing: 0 }
]
};
}
]);
})();
Angular.html
<div class="row clearfix" ng-controller="app.views.automate as vm">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<div class="card">
<div class="header">
<h2>
Automate
</h2>
</div>
<div class="body">
<div id="wizard-step-container">
<ul class="nav nav-pills nav-justified">
<li ng-repeat="step in vm.steps" ng-class="{'active':step.step == vm.currentStep}"><a ng-click="vm.gotoStep(step.step)" href="">{{step.step}}. {{step.name}}</a></li>
</ul>
</div>
<div id="wizard-content-container">
<ng-include src="vm.getStepTemplate()"></ng-include>
</div>
<div id="wizard-navigation-container">
<div class="pull-right">
<span class="btn-group">
<button ng-disabled="vm.currentStep <= 1" class="btn btn-default" name="previous" type="button" ng-click="vm.gotoStep(vm.currentStep - 1)"><i class="fa fa-arrow-left"></i> Previous step</button>
<button ng-disabled="vm.currentStep >= vm.steps.length" class="btn btn-primary" name="next" type="button" ng-click="vm.gotoStep(vm.currentStep + 1)">Next step <i class="fa fa-arrow-right"></i></button>
</span>
<button ng-disabled="vm.currentStep != vm.steps.length" class="btn btn-success" name="next" type="button" ng-click="vm.save()"> <i class="fa fa-floppy-o"></i> Save</button>
</div>
</div>
</div>
</div>
</div>
</div>
Step1.html
<div class="step1">
<div class="loading-icon" id="loading" ng-show="showLoader">
</div>
<div class="form-inline">
<input type="file" class="form-control" name="file" accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel" onchange="angular.element(this).scope().UploadFiles(this.files)" />
<input type="button" value="Preview" class="btn btn-primary" ng-disabled="!SelectedFileForUpload" ng-click="ParseExcel()" />
<input type="button" value="Insert" style="margin-left: 15px;" class="btn btn-success" ng-show="IsVisible" ng-click="InsertData()" />
</div>
<br />
</div>
Excel.js
(function () {
angular.module('app').controller('app.views.excel', [
'$scope', 'abp.services.app.excel',
function ($scope, ExcelService) {
var vm = this;
$scope.ParseExcel = function () {
var formData = new FormData();
var file = $scope.SelectedFileForUpload;
formData.append('file', file);
$scope.showLoader = true; //show spinner
var response = Excelservice.SendExcelData(formData); //calling service
response.then(function (d) {
var res = d.data;
$scope.BindData = res;
$scope.IsVisible = true; //showing the table after databinding
$scope.showLoader = false; //after success hide spinner
}, function (err) {
console.log(err.data);
console.log("error in parse excel");
});
}
$scope.InsertData = function () {
var response = Excelservice.InsertToDB();
response.then(function (d) {
var res = d.data;
if (res.toString().length > 0) {
$scope.Message = res + " Records Inserted";
$scope.IsVisible = false; //used to disable the insert button and table after submitting data
angular.forEach(
angular.element("input[type='file']"),
function (inputElem) {
angular.element(inputElem).val(null); //used to clear the file upload after submitting data
});
$scope.SelectedFileForUpload = null; //used to disable the preview button after inserting data
}
}, function (err) {
console.log(err.data);
console.log("error in insertdata");
});
}
}
]);
angular.module('app').service("Excelservice", function ($http) {
this.SendExcelData = function (data) {
var request = $http({
method: "post",
withCredentials: true,
url: '/Home/ReadExcel',
data: data,
headers: {
'Content-Type': undefined
},
transformRequest: angular.identity
});
return request;
}
this.InsertToDB = function () {
var request = $http({
method: "get",
url: '/Home/InsertExcelData',
data: {},
datatype: 'json'
});
return request;
}
});
//used to check the extension of file while uploading
function checkfile(sender) {
var validExts = new Array(".xlsx", ".xls");
var fileExt = sender.value;
fileExt = fileExt.substring(fileExt.lastIndexOf('.'));
if (validExts.indexOf(fileExt) < 0) {
alert("Invalid file selected, valid files are of " +
validExts.toString() + " types.");
return false;
}
else return true;
}
})();
Error Details
(function () {
var controllerId = 'app.views.automate';
angular.module('app').controller(controllerId, [
'$scope','Excelservice', 'abp.services.app.automate', function ($scope, Excelservice, automateService) {
var vm = this;
// ...
}]);
})();
https://github.com/aspnetboilerplate/aspnetboilerplate/issues/3789#issuecomment-416031257

Displaying data in ng-grid by clicking on an <a> element in the sidebar

I have a view in an angularjs application with a sidebar, where I can choose my insurers. By clicking on an insurer, I want my ng-grid show me some insurer's data. Now I can select the insurer, and see the <div class="well well-sm"> changes.
Here is my angular controller:
app.controller('ReportsInsurerPaymentsCtrl', ['$scope', '$http', '$filter', 'toaster', '$state', '$modal', function ($scope, $http, $filter, toaster, $state, $modal) {
$scope.insurer_payments = [];
$scope.insurer_payments = [];
$scope.insurer_payment = {};
$scope.gridOptions = {
data: "insurer_payment",
rowTemplate: '<div ng-style="{\'cursor\': row.cursor, \'z-index\': col.zIndex() }" ng-repeat="col in renderedColumns" ng-class="col.colIndex()" class="ngCell {{col.cellClass}} " ng-cell></div>',
columnDefs: [
{
field: "date",
displayName: "Date",
cellTemplate: '<div class="ngCellText" ng-class="col.colIndex()"><span ng-cell-text>{{row.getProperty(col.field)}}</span></div>',
width: 100
},
{
field: "amount",
displayName: "Amount",
cellTemplate: '<div class="ngCellText" ng-class="col.colIndex()"><span ng-cell-text>{{row.getProperty(col.field)}}</span></div>'
},
{
field: 'comment',
displayName: 'Comment',
cellTemplate: '<div class="ngCellText" ng-class="col.colIndex()"><span ng-cell-text>{{row.getProperty(col.field)}}</span></div>',
}
],
$scope.refresh = function () {
var p = {
name: $scope.filterOptions.filterText,
pageNumber: (allPages >= $scope.pagingOptions.currentPage) ? $scope.pagingOptions.currentPage : $scope.pagingOptions.currentPage = 1,
pageSize: $scope.pagingOptions.pageSize,
sortInfo: sb.join("")
};
$http({
url: "reports/insurer_payments.json",
method: "GET",
params: p
}).success(function (data, insurer_payment) {
$scope.totalServerItems = data.insurerPaymentsCount;
$scope.insurer_payments_count = data.total_insurer_payments_count;
$scope.insurer_payments = data.insurer_payments;
$scope.insurer_payment = data.insurer_payment;
if (insurer_payment) {
$scope.insurer_payment = $filter('orderBy')($scope.insurer_payments, 'name')[0];
} else {
$scope.insurer_payment = $filter('filter')($scope.insurer_payments, {name: insurer_payment.name})[0];
}
if ($scope.insurer_payments) $scope.insurer_payment.selected = true;
$scope.showContent = true;
if ($scope.gridOptions.ngGrid) {
$scope.gridOptions.ngGrid.buildColumns();
}
}).error(function () {
});
}, 100);
};
$scope.selectInsurerPayment = function(item){
angular.forEach($scope.insurer_payments, function(item) {
item.selected = false;
});
$scope.insurer_payment = item;
$scope.insurer_payment.selected = true;
};
$scope.refresh();
}]);
A part of a view:
<a ng-repeat="insurer_payment in insurer_payments | orderBy:'name'"
class="list-group-item m-l"
ng-class="{'select m-l-none': insurer_payment.selected }"
ng-click="selectInsurerPayment(insurer_payment)">
<span class="block text-ellipsis m-l-n text-md" ng-class="{'m-l-none': insurer_payment.selected }">
{{ insurer_payment.name }}
</span>
</a>
<div class="well well-sm">
<div class="row">
<div class="col-sm-4">
<strong>Commission: {{insurer_payment.commission}}</strong>
</div>
<div class="col-sm-4">
<strong>Insurer Ppayment: {{insurer_payment.insurer_payment}}</strong>
</div>
<div class="col-sm-4">
<strong>Inequality: {{insurer_payment.commission - insurer_payment.insurer_payment}}</strong>
</div>
</div>
</div>
<div class="table-responsive">
<div ng-grid="gridOptions" class="gridStyle">
</div>
</div>
And a part of a rails controller:
def index
insurer_payments = current_company.insurers.map do |insurer|
{
commission: insurer.contracts.pluck(:commission).sum.to_f,
name: insurer.name,
insurer_payment: insurer.insurer_payments.pluck(:amount).sum.to_f,
id: insurer.id
}
end
insurer_payment = current_company.insurers.map do |insurer|
{
amount: insurer.insurer_payments.pluck(:amount).map { |x| x.to_f },
comment: insurer.insurer_payments.pluck(:comment),
date: insurer.insurer_payments.pluck(:date),
id: insurer.id
}
end
total_insurer_payments_count = current_company.insurers.map do |insurer|
insurer.insurer_payments.count
end
insurer_payments_count = current_company.insurer_payments.count
respond_to do |format|
format.json { render json: { insurer_payments: insurer_payments, insurer_payment: insurer_payment,
total_insurer_payments_count: total_insurer_payments_count,
insurerPaymentsCount: insurer_payments_count } }
end
end
So, how it can be done, by selecting an insurer to see the corresponding data?
I am not sure on this, since I don't have all of your code, but you may want to try some of the changes I have below.
Because ng-repeat has it's own scope, iterating through insurer_payment in insurer_payments is conflicting with insurer_payment on scope. When you loop through the insurer_payments, you are modifying the value of insurer_payment each time.
I would change
$scope.gridOptions = {
data: "insurer_payment",
to
$scope.gridOptions = {
data: [];
Since the data is an array, not a string.
Within the success callback of $http, you need to set gridOptions.data (unless this is elsewhere, I don't see where the grid is)
.success(function (data, insurer_payment) {
$scope.gridOptions.data = data;
...
}
And the selectInsurerPayment function:
$scope.selectInsurerPayment = function(item){
angular.forEach($scope.insurer_payments, function(item) {
item.selected = false;
});
$scope.selectedInsurerPayment = item;
$scope.insurer_payment.selected = true;
};
And finally, in the well in your HTML, change references to insurer_payment to selectedInsurerPayment, ex:
<strong>Commission: {{selectedInsurerPayment.commission}}</strong>
Old Solution
In ng-repeat:
ng-click="selectInsurerPayment(insurer_payment)"
to
ng-click="selection.insurer_payment = insurer_payment"
In the well,
<div class="well well-sm">
to
<div class="well well-sm" ng-if="selection.insurer_payment">
and change the references to insurer_payment to selection.insurer_payment.{variable}, example:
<strong>Commission: {{selection.insurer_payment.commission}}</strong>

Delete a row and disable checkbox in dropdown-multiselect at the same time angularsjs

I have a problem with angularsJs, I have a dropdown-multiselect which contain a checkbox button with labels, when I click check, the label is addded in the table,
now, I want to delete a row in the table, so I have to click (supprimer) button (in the table) and I need in the same time that the check will be uncheked and I don't know how to proceed
Please some one could help me please
this is my popup.html page :
<!DOCTYPE html>
<html>
<head>
<title></title>
<link href="css/bootstrap.min.css" rel="stylesheet">
<script src="js/angular.js"></script>
<script src="js/angular-resource.js"></script>
<script src="js/angular-route.js"></script>
<script src="js/jquery.min.js"></script>
<script src="js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.11.0/lodash.min.js"></script>
<script src="js/MyApp.js"></script>
<link href="font-awesome-4.6.0/css/font-awesome.min.css" rel="stylesheet" type="text/css">
</head>
<body >
<div ng-app="myApp" ng-controller="AppCtrl">
<div ng-dropdown-multiselect="" options="example14data" selected-model="example14model" checkboxes="true" extra-settings="example14settings"></div>
<form class="form-inline" role="form" style="margin-left: 300px;">
<div class="form-group">
<input type="text" size="30" placeholder=" other subject" class="form-control" ng-model="otherSubject" />
</div>
<div class="form-group">
<button class="btn btn-default" ng-click="ajouteSubject(otherSubject)" >Ajouter</button>
<button ng-click="supprimer()"> <a><i class="fa fa-remove" ng-click="supprimer()"></i></a>supprimer</button>
</div>
</form><br>
<table class="table table-responsive table-bordered" style="width:400px; margin-left: 300px;">
<thead>
<tr>
<th>Subject Name</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="pref in example14model">
<td>{{pref.label}}</td>
<td> <input type="checkbox" ng-model="pref.isDelete"/> {{$index}}</td>
</tr>
</tbody>
</table>
<br><br>
<pre>Selected Subject: {{example14model}} | </pre>
</div>
</body>
</html>
and My controller myApp.js
'use strict';
var app = angular.module('myApp', ['angularjs-dropdown-multiselect']);
app.controller('AppCtrl', function ($scope) {
$scope.example14model = [];
$scope.example14settings = {
scrollableWidth: '400px',
scrollableHeight: '200px',
scrollable: true,
enableSearch: true
};
$scope.example14data = [
{ "label": "JAVA", "id": "1" },
{ "label": "C++", "id": "2" },
{ "label": "JSON", "id": "3" },
{ "label": "DotNet", "id": "4"},
{"label": "AKKA", "id": "5"}
];
$scope.example2settings = {
displayProp: 'label'
};
$scope.ajouteSubject = function (otherSubject) {
$scope.example14data.push({
label: otherSubject,
checked: false
})
};
$scope.supprimer= function (){
var example14dataNew= [];
angulars.forEach($scope.example14data, function(v){
if (!v.isDelete){
example14dataNew.push(v);
}
$scope.example14data= example14dataNew;
} )
};
$scope.sessions = [{
id: 0
}];
});
var directiveModule = angular.module('angularjs-dropdown-multiselect', []);
directiveModule.directive('ngDropdownMultiselect', ['$filter', '$document', '$compile', '$parse',
function ($filter, $document, $compile, $parse) {
return {
restrict: 'AE',
scope: {
selectedModel: '=',
options: '=',
extraSettings: '=',
events: '=',
searchFilter: '=?',
translationTexts: '=',
groupBy: '#'
},
template: function (element, attrs) {
var checkboxes = attrs.checkboxes ? true : false;
var groups = attrs.groupBy ? true : false;
var template = '<div class="multiselect-parent btn-group dropdown-multiselect" style="width: 300px">';
template += '<button type="button" class="dropdown-toggle" ng-class="settings.buttonClasses" ng-click="toggleDropdown()">{{getButtonText()}} <span class="caret"></span></button>';
template += '<ul class="dropdown-menu dropdown-menu-form" ng-style="{display: open ? \'block\' : \'none\', height : settings.scrollable ? settings.scrollableHeight : \'auto\' }" style="overflow: scroll" >';
template += '<li ng-hide="!settings.showCheckAll || settings.selectionLimit > 0"><a data-ng-click="selectAll()"><i class="fa fa-check"></i> {{texts.checkAll}}</a>';
template += '<li ng-show="settings.showUncheckAll"><a data-ng-click="deselectAll();"><i class="fa fa-remove"></i> {{texts.uncheckAll}}</a></li>';
template += '<li ng-hide="(!settings.showCheckAll || settings.selectionLimit > 0) && !settings.showUncheckAll" class="divider"></li>';
template += '<li ng-show="settings.enableSearch"><div class="dropdown-header"><input type="text" class="form-control" style="width: 100%;" ng-model="searchFilter" placeholder="{{texts.searchPlaceholder}}" /></li>';
template += '<li ng-show="settings.enableSearch" class="divider"></li>';
if (groups) {
template += '<li ng-repeat-start="option in orderedItems | filter: searchFilter" ng-show="getPropertyForObject(option, settings.groupBy) !== getPropertyForObject(orderedItems[$index - 1], settings.groupBy)" role="presentation" class="dropdown-header">{{ getGroupTitle(getPropertyForObject(option, settings.groupBy)) }}</li>';
template += '<li ng-repeat-end role="presentation">';
} else {
template += '<li role="presentation" ng-repeat="option in options | filter: searchFilter">';
}
template += '<a role="menuitem" tabindex="-1" ng-click="setSelectedItem(getPropertyForObject(option,settings.idProp))">';
if (checkboxes) {
template += '<div class="checkbox"><label><input class="checkboxInput" type="checkbox" ng-click="checkboxClick($event, getPropertyForObject(option,settings.idProp))" ng-checked="isChecked(getPropertyForObject(option,settings.idProp))" /> {{getPropertyForObject(option, settings.displayProp)}}</label></div></a>';
} else {
template += '<span data-ng-class="{\'glyphicon glyphicon-ok\': isChecked(getPropertyForObject(option,settings.idProp))}"></span> {{getPropertyForObject(option, settings.displayProp)}}</a>';
}
template += '</li>';
template += '<li class="divider" ng-show="settings.selectionLimit > 1"></li>';
template += '<li role="presentation" ng-show="settings.selectionLimit > 1"><a role="menuitem">{{selectedModel.length}} {{texts.selectionOf}} {{settings.selectionLimit}} {{texts.selectionCount}}</a></li>';
template += '</ul>';
template += '</div>';
element.html(template);
},
link: function ($scope, $element, $attrs) {
var $dropdownTrigger = $element.children()[0];
$scope.toggleDropdown = function () {
$scope.open = !$scope.open;
};
$scope.checkboxClick = function ($event, label) {
$scope.setSelectedItem(label);
$event.stopImmediatePropagation();
};
$scope.externalEvents = {
onItemSelect: angular.noop,
onItemDeselect: angular.noop,
onSelectAll: angular.noop,
onDeselectAll: angular.noop,
onInitDone: angular.noop,
onMaxSelectionReached: angular.noop
};
$scope.settings = {
dynamicTitle: true,
scrollable: false,
scrollableWidth: '300px',
scrollableHeight: '300px',
closeOnBlur: true,
displayProp: 'label',
idProp: 'label',
externalIdProp: 'label',
enableSearch: false,
selectionLimit: 0,
showCheckAll: true,
showUncheckAll: true,
closeOnSelect: false,
buttonClasses: 'btn btn-default',
closeOnDeselect: false,
groupBy: $attrs.groupBy || undefined,
groupByTextProvider: null,
smartButtonMaxItems: 0,
smartButtonTextConverter: angular.noop
};
$scope.texts = {
checkAll: 'Check All',
uncheckAll: 'Uncheck All',
selectionCount: 'checked',
selectionOf: '/',
searchPlaceholder: 'Search...',
buttonDefaultText: 'Select a subject',
dynamicButtonTextSuffix: 'checked'
};
$scope.searchFilter = $scope.searchFilter || '';
if (angular.isDefined($scope.settings.groupBy)) {
$scope.$watch('options', function (newValue) {
if (angular.isDefined(newValue)) {
$scope.orderedItems = $filter('orderBy')(newValue, $scope.settings.groupBy);
}
});
}
angular.extend($scope.settings, $scope.extraSettings || []);
angular.extend($scope.externalEvents, $scope.events || []);
angular.extend($scope.texts, $scope.translationTexts);
$scope.singleSelection = $scope.settings.selectionLimit === 1;
function getFindObj(label) {
var findObj = {};
if ($scope.settings.externalIdProp === '') {
findObj[$scope.settings.idProp] = label;
} else {
findObj[$scope.settings.externalIdProp] = label;
}
return findObj;
}
function clearObject(object) {
for (var prop in object) {
delete object[prop];
}
}
if ($scope.singleSelection) {
if (angular.isArray($scope.selectedModel) && $scope.selectedModel.length === 0) {
clearObject($scope.selectedModel);
}
}
if ($scope.settings.closeOnBlur) {
$document.on('click', function (e) {
var target = e.target.parentElement;
var parentFound = false;
while (angular.isDefined(target) && target !== null && !parentFound) {
if (_.contains(target.className.split(' '), 'multiselect-parent') && !parentFound) {
if (target === $dropdownTrigger) {
parentFound = true;
}
}
target = target.parentElement;
}
if (!parentFound) {
$scope.$apply(function () {
$scope.open = false;
});
}
});
}
$scope.getGroupTitle = function (groupValue) {
if ($scope.settings.groupByTextProvider !== null) {
return $scope.settings.groupByTextProvider(groupValue);
}
return groupValue;
};
$scope.getButtonText = function () {
if ($scope.settings.dynamicTitle && ($scope.selectedModel.length > 0 || (angular.isObject($scope.selectedModel) && _.keys($scope.selectedModel).length > 0))) {
if ($scope.settings.smartButtonMaxItems > 0) {
var itemsText = [];
angular.forEach($scope.options, function (optionItem) {
if ($scope.isChecked($scope.getPropertyForObject(optionItem, $scope.settings.idProp))) {
var displayText = $scope.getPropertyForObject(optionItem, $scope.settings.displayProp);
var converterResponse = $scope.settings.smartButtonTextConverter(displayText, optionItem);
itemsText.push(converterResponse ? converterResponse : displayText);
}
});
if ($scope.selectedModel.length > $scope.settings.smartButtonMaxItems) {
itemsText = itemsText.slice(0, $scope.settings.smartButtonMaxItems);
itemsText.push('...');
}
return itemsText.join(', ');
} else {
var totalSelected;
if ($scope.singleSelection) {
totalSelected = ($scope.selectedModel !== null && angular.isDefined($scope.selectedModel[$scope.settings.idProp])) ? 1 : 0;
} else {
totalSelected = angular.isDefined($scope.selectedModel) ? $scope.selectedModel.length : 0;
}
if (totalSelected === 0) {
return $scope.texts.buttonDefaultText;
} else {
return totalSelected + ' ' + $scope.texts.dynamicButtonTextSuffix;
}
}
} else {
return $scope.texts.buttonDefaultText;
}
};
$scope.getPropertyForObject = function (object, property) {
if (angular.isDefined(object) && object.hasOwnProperty(property)) {
return object[property];
}
return '';
};
$scope.selectAll = function () {
$scope.deselectAll(false);
$scope.externalEvents.onSelectAll();
angular.forEach($scope.options, function (value) {
$scope.setSelectedItem(value[$scope.settings.idProp], true);
});
};
$scope.deselectAll = function (sendEvent) {
sendEvent = sendEvent || true;
if (sendEvent) {
$scope.externalEvents.onDeselectAll();
}
if ($scope.singleSelection) {
clearObject($scope.selectedModel);
} else {
$scope.selectedModel.splice(0, $scope.selectedModel.length);
}
};
$scope.setSelectedItem = function (label, dontRemove) {
var findObj = getFindObj(label);
var finalObj = null;
if ($scope.settings.externalIdProp === '') {
finalObj = _.find($scope.options, findObj);
} else {
finalObj = findObj;
}
if ($scope.singleSelection) {
clearObject($scope.selectedModel);
angular.extend($scope.selectedModel, finalObj);
$scope.externalEvents.onItemSelect(finalObj);
if ($scope.settings.closeOnSelect) $scope.open = false;
return;
}
dontRemove = dontRemove || false;
var exists = _.findIndex($scope.selectedModel, findObj) !== -1;
if (!dontRemove && exists) {
$scope.selectedModel.splice(_.findIndex($scope.selectedModel, findObj), 1);
$scope.externalEvents.onItemDeselect(findObj);
} else if (!exists && ($scope.settings.selectionLimit === 0 || $scope.selectedModel.length < $scope.settings.selectionLimit)) {
$scope.selectedModel.push(finalObj);
$scope.externalEvents.onItemSelect(finalObj);
}
if ($scope.settings.closeOnSelect) $scope.open = false;
};
$scope.isChecked = function (label) {
if ($scope.singleSelection) {
return $scope.selectedModel !== null && angular.isDefined($scope.selectedModel[$scope.settings.idProp]) && $scope.selectedModel[$scope.settings.idProp] === getFindObj(label)[$scope.settings.idProp];
}
return _.findIndex($scope.selectedModel, getFindObj(label)) !== -1;
};
$scope.externalEvents.onInitDone();
}
};
}]);
Try this:
Replace:
<td> <a><i class="fa fa-remove" ng-click="supprimer()"></i></a>supprimer</td>
With this:
<td> <a><i class="fa fa-remove" ng-click="supprimer($index)"></i></a>supprimer</td>
And then in your controller do this:
$scope.supprimer = function(index) {
$scope.example14model.splice(index, 1);
}
Good luck :)

Angular UI Bootstrap modal result is undefined

I'm building an app that loads a modal on a click on a button in an ng-grid row. Displaying the modal and the correct data works great. Problem is with getting the data back form the form in the modal. This bit of code
modalInstance.result.then(function(selectedItem){
$scope.selected = selectedItem;
});
Returns 'undefined' for 'selectedItem'
Here's the modal.
<div ng-app="myApp">
<div ng-controller="UsersCtrl">
<script type="text/ng-template" id="editUserModal.html">
<div class="modal-header">
<h3 class="modal-title">Edit User <em>{{user.user_full_nm}} {{user.user_id}}</em></h3>
</div>
<div class="modal-body">
<p>User Name: <input type="text" name="user_full_nm" value="{{user.user_full_nm}}"></p>
<p>Email: <input type="text" name="user_nm" value="{{user.user_nm}}"></p>
<p>Active:
<select ng-model="user.deleted" ng-selected="user.deleted">
<option value="0" ng-selecte>Active</option>
<option value="1">Inactive</option>
</select>
</p>
<p>Termination Date: {{user.termination_date | date:'longDate'}}</p>
<p>Last Entry Date: {{user.last_entry | date:'longDate'}}</p>
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="ok()">OK</button>
<button class="btn btn-warning" ng-click="cancel()">Cancel</button>
</div>
</script>
<div class="gridStyle" ng-grid="gridOptions"></div>
</div>
</div>
Here's the Angular app.
var app = angular.module('myApp', ['ngGrid','ui.bootstrap']);
app.controller('UsersCtrl', function($scope, $http, $modal) {
$scope.filterOptions = {
filterText: "",
useExternalFilter: false
};
$scope.totalServerItems = 0;
$scope.pagingOptions = {
pageSizes: [20, 40, 60],
pageSize: 20,
currentPage: 1
};
$scope.setPagingData = function(data, page, pageSize){
var pagedData = data.slice((page - 1) * pageSize, page * pageSize);
$scope.userData = pagedData;
$scope.totalServerItems = data.length;
if (!$scope.$$phase) {
$scope.$apply();
}
};
$scope.getPagedDataAsync = function (pageSize, page, searchText) {
setTimeout(function () {
var data;
if (searchText) {
var ft = searchText.toLowerCase();
$http.get('getUsers').success(function (largeLoad) {
data = largeLoad.filter(function(item) {
return JSON.stringify(item).toLowerCase().indexOf(ft) != -1;
});
$scope.setPagingData(data,page,pageSize);
});
} else {
$http.get('getUsers').success(function (largeLoad) {
$scope.setPagingData(largeLoad,page,pageSize);
});
}
}, 100);
};
$scope.getPagedDataAsync($scope.pagingOptions.pageSize, $scope.pagingOptions.currentPage);
$scope.$watch('pagingOptions', function (newVal, oldVal) {
if (newVal !== oldVal && newVal.currentPage !== oldVal.currentPage) {
$scope.getPagedDataAsync($scope.pagingOptions.pageSize,$scope.pagingOptions.currentPage,$scope.filterOptions.filterText);
}
}, true);
$scope.$watch('filterOptions', function (newVal, oldVal) {
if (newVal !== oldVal) {
$scope.getPagedDataAsync($scope.pagingOptions.pageSize, $scope.pagingOptions.currentPage,
$scope.filterOptions.filterText);
}
}, true);
var editUserButtonTemplate = '<i class="fa fa-pencil" style="cursor:pointer;" ng-click="editUser(row.entity)"></i>';
$scope.gridOptions = {
data: 'userData',
columnDefs: [
{field: 'user_id', displayName: 'User ID', visible: false},
{field: 'user_nm', displayName: 'Email'},
{field: 'user_full_nm', displayName: 'Name'},
{field: 'deleted', displayName: 'Active', width: 60, cellFilter: 'activeFilter'},
{field: 'termination_date', displayName: 'Termination Date',cellFilter: 'date:\'longDate\''},
{field: 'last_entry', displayName: 'Last Entry Date',cellFilter: 'date:\'longDate\''},
{field: '', DisplayName: '', cellTemplate: editUserButtonTemplate, colFilterText: '', width:20}
],
enablePaging: true,
showFooter: true,
showFilter: true,
enableRowSelection: false,
filterOptions: $scope.filterOptions,
totalServerItems:'totalServerItems',
pagingOptions: $scope.pagingOptions,
filterOptions: $scope.filterOptions
};
/************ open the edit user modal *********************/
$scope.editUser = function(value) {
var modalInstance = $modal.open({
templateUrl: 'editUserModal.html',
// scope: $scope,
controller: 'editUserCtrl',
resolve: {
user: function () {
return value;
}
}
});
modalInstance.result.then(function(selectedItem){
$scope.selected = selectedItem;
});
};
});
app.controller('editUserCtrl', function($scope, $http, $modalInstance, user) {
$scope.user = user;
$scope.ok = function () {
$modalInstance.close($scope.selected);
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
});
// for the 'deleted' column, display 'Active' or 'Inactive' instead of 1 or 0
app.filter('activeFilter', function(){
var types = ['Active', 'Inactive'];
return function(type){
return types[type];
};
});
So as happens so often, as soon as I posted my question I found this one.
angular-ui-bootstrap modal not passing back result
Which led me to the problem.
$scope.ok = function () {
$modalInstance.close($scope.selected);
};
Changed $scope.selected to $scope.user and it's working as expected now.

AngularJS UI ng-grid not painting content text & blank when used inside directive

I am developing one SearchAndSelect control (AngularJS directive) which contains it's own ng-grid, slider page. Everything is working, data is being fetched, number of rows are coming to the grid, but grid is not showing text.
SearchAndSelectDirective.js
App.directive('searchAndSelect',
function () {
return {
restrict: 'E',
templateUrl: "/app/directives/searchAndSelect.html",
controller: "searchAndSelectController",
transclude: false,
scope: {
currentNode: '='
},
compile: function() {
// return true;
}
};
}
);
SearchAndSelect.html
<button class="btn" ng-click="openSliderPage()">Add/Remove {{EntityName}}</button>
<div id="divSlide" class="sliderDiv">
<div class="sliderHeader" ng-model="partialPageHeading">
<span class="sliderHeaderLabelOriginal">{{partialPageHeading}}</span>
</div>
<div>
<div class="gridStyle" ng-grid="gridOptions"></div>
<div class="modal-footer">
<input ng-model="filterOptions.filterText" />
<button class="btn btn-info" ng-click="getPagedDataAsync()">Filter</button>
<button class="btn btn-primary" ng-click="add()">Update</button>
<button class="btn btn-warning" ng-click="cancnel()">Cancel</button>
</div>
</div>
<!--<ng-include src="svcSliderView"></ng-include>-->
</div>
It has got it's own controller, which fetches the data in async manner. Number of rows are being generated within the grid, grid is visible. I have code inside controller to mark some rows selected, and it is happening. But only the content is not being displayed. If I see browser's element exploration, I can see the data is there.
SearchAndSelectController.js
$scope.filterOptions = {
filterText: "",
useExternalFilter: false
};
$scope.pagingOptions = {
pageSizes: [50, 100, 200],
pageSize: 50,
currentPage: 1
};
$scope.getVehListParams = function () {
var params = { PageNo: $scope.pagingOptions.currentPage, PageSize: $scope.pagingOptions.pageSize };
params.CalculateTotal = false;
if (!$scope.totalCount) {
params.CalculateTotal = true;
}
params.FilterText = '';
if ($scope.filterOptions.filterText) {
params.FilterText = $scope.filterOptions.filterText;
}
return params;
};
$scope.getPagedDataAsync = function () {
var vehListGetParams = $scope.getVehListParams();
seVehicleResource.get(vehListGetParams,
function (result) {
$scope.dataList = result.DataList;
if (result.TotalCount || result.TotalCount == 0) {
$scope.totalCount = result.TotalCount;
}
//mark already added rows in left as selected.
$timeout(function () {
if ($scope.planSelected) {
_.each($scope.planSelected.Vehicles, function (vehicle) {
var vIdx = $.map(result.DataList, function (obj, index) {
if (obj.VehicleId == vehicle.VehicleId) {
return index;
}
return null;
});
if (vIdx && vIdx.length > 0) {
$scope.vehicleExisted.push(result.DataList[vIdx[0]]);
$scope.gridOptions.selectItem(vIdx[0], true);
}
});
}
});
}, function (error) {
console.log(error);
});
};
$scope.$watch('pagingOptions', function (newVal, oldVal) {
if (newVal !== oldVal && (newVal.currentPage !== oldVal.currentPage || newVal.pageSize !== oldVal.pageSize)) {
$scope.getPagedDataAsync();
}
}, true);
$scope.allSelected = false;
$scope.gridOptions = {
data: 'dataList',
enablePaging: true,
showFooter: true,
showFilter: true,
columnDefs: [{ field: 'Make', displayName: 'Make', width: '35%' }, { field: 'Model', displayName: 'Model', width: '35%' }, { field: 'BeginYear', displayName: 'Begin Year', width: '15%' }, { field: 'EndYear', displayName: 'End Year', width: '15%' }],
totalServerItems: 'totalCount',
pagingOptions: $scope.pagingOptions,
filterOptions: $scope.filterOptions.filterText,
showSelectionCheckbox: true,
afterSelectionChange: $scope.afterSelectionChange,
};
I used this directive inside following div, which made its fontsize to 0, removing this container grid, fixed my issue.
Thanks All
<div class="btn-group">

Resources