Angular table last added row not loading bootstrap calendar - angularjs

I am using angular to load meeting information into a table. When i try to add a new row to the table, the added row does not load the last bootstrap calendar because angular hasn't yet finished loading the row when i call a function to dynamically load the datepicker. How can i call load the datepicker after Angular has finished loading the new row?
Here's my code:
<div ng-controller="virtualmeetingdetails" id="virtualmeetingdetails">
<div class="row" id="proposedaddboards">
<div class="form-group required">
<label id="adboardnumber" class="control-label col-sm-4" for="spinner1">Proposed Number of Advisory Boards</label>
<div class="col-sm-4">
<div id="spinnerDiv1" class="input-group spinner">
<asp:TextBox id="spinner1" cssclass="form-control" value="0" runat="server" />
<div class="input-group-btn-vertical">
<button class="btn btn-default" type="button" ng-click="addUser()"><i class="fa fa-caret-up"></i></button>
<button class="btn btn-default" type="button"><i class="fa fa-caret-down"></i></button>
</div>
</div>
</div>
</div>
</div>
<div class="row" id="tblVirtualMeeting">
<div class="form-group required">
<div class="col-sm-12" >
<table class="table table-bordered table-striped" jq-table>
<thead style="background-color:#cad4d9">
<tr>
<th>Proposed Date</th>
<th>Virtual Meeting</th>
<th>Location City</th>
<th>State</th>
<th>Country</th>
<th></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="meeting in meetings">
<td>
<div class="input-group input-append date" id="dtpicker{{$index}}" data-date-format="mm/dd/yyyy" style="width:150px;">
<span class="text-center" ng-show="editMode">{{meeting.proposedbegindate}}</span>
<input type="text" class="form-control col-sm-3" runat="server" ng-hide="editMode" ng-model="meeting.proposedbegindate" />
<span class="input-group-addon add-on" ng-hide="editMode">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</td>
<td>
<select ng-model="meeting.isvirtualmeeting" ng-hide="editMode"
ng-options="option.text for option in virtualmeetingoptions track by option.value" class="form-control">
</select>
<span class="text-center" ng-show="editMode">{{meeting.isvirtualmeeting.text}}</span>
</td>
<td>
<span class="text-center" ng-show="editMode">{{meeting.venuecity}}</span>
<input type="text" class="form-control" ng-hide="editMode" ng-model="meeting.venuecity" />
</td>
<td>
<select ng-model="meeting.venuestateID" ng-hide="editMode" ng-options="state.StateConst for state in statesList track by state.StateID" class="form-control"></select>
<span class="text-center" ng-show="editMode">{{meeting.venuestateID.StateConst}}</span>
</td>
<td>
<select ng-model="meeting.venuecountryid" ng-hide="editMode" ng-options="country.CountryName for country in countriesList track by country.CountryID" class="form-control"></select>
<span class="text-center" ng-show="editMode">{{meeting.venuecountryid.CountryConst}}</span>
</td>
<td style="width:170px">
<span class="glyphicon glyphicon-pencil" style="color: green; font-size: medium; cursor: pointer" ng-show="editMode" ng-click="editMode = false; editUser(participant)"></span>
<span class="glyphicon glyphicon-floppy-save" style="color: #337ab7; font-size: medium; cursor: pointer" ng-hide="editMode" ng-click="editMode = true;saveField(meeting, <%=_CurrentUserID %>);"></span>
<span class="glyphicon glyphicon-remove-circle" style="color: red;font-size:medium;cursor:pointer" ng-click="removeItem($index)"></span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
Controller:
app.controller("virtualmeetingdetails", function ($scope, $http) {
$http.get("../Services/EngagementDataService.asmx/GetVirtualMeetings", { params: { 'mid': getParameterByName('mid')} })
.success(function (response) {
var j = response.length;
var i = 0;
if (response.length > 0) {
while (i < j) {
response[i].proposedbegindate = moment(response[i].proposedbegindate).format("MM/DD/YYYY");
i++
}
}
....more code goes here (removed)
$scope.addUser = function () {
$scope.editing = true;
var meetingcount;
if (typeof $scope.meetings === "undefined")
meetingcount = 0
else meetingcount = $scope.meetings.length;
$scope.inserted = {
engagementproposedinfoid: 0,
id: meetingcount + 1,
venuecity: '',
proposedbegindate: '',
venuestateid: 0,
venuecountryid: 1,
isvirtualmeeting: 0
};
$scope.meetings.push($scope.inserted);
rendercalendars(meetingcount);
};
});
Function to render datepicker:
function rendercalendars(rows) {
var nowDate = new Date();
var today = new Date(nowDate.getFullYear(), nowDate.getMonth(), nowDate.getDate(), 0, 0, 0, 0);
var j = rows;
var i = 0;
while (i < j) {
$('#dtpicker' + i).datepicker({ autoclose: true, startDate: today });
i++
}
}
The issue happens when $scope.addUser gets called... it loads the table row before the rendercalendars function gets called so the datepickers don't get loaded.
Any help will be appreciated.

My guess would be something like this:
With this line you change your scope and on your next digest cycle your repeat will be "redone". So your html gets adjusted.
$scope.meetings.push($scope.inserted);
Then you call your render function and its all messed up if the digest hit before.
rendercalendars(meetingcount);
But that's just a guess of mine.
BTW there is an angular implementation for bootstrap components (ui-boostrap) then you don't have to do jQuery stuff.
Home this is some sort of help.

Related

using Angularjs How to bind dropdown value control from the table by clicking on edit button?

i only bind the drop-down related value, by clicking on edit button within table, its not working within drop-down
Here is my angularjs code
myapp = angular
.module('myapp', ["ui.router", 'ngAnimate', 'angular-loading-bar', 'ui-notification', 'smart-table', 'ui.bootstrap'])
.controller('DemoCtrl', function ($scope, $interval, Notification, cfpLoadingBar, $http) {
GetAll();
function GetAll() {
$http.get("/api/AddCatagories").then(function (response) {
$scope.cate = response.data
}, function () {
alert("Error")
})
}
$scope.subcateedit = function (Id) {
$http.get("/api/AddSubCatagories/" + Id).then(function (response) {
cfpLoadingBar.start();
$scope.SubCata = response.data
cfpLoadingBar.complete();
})
}
})
Html Table Code is here you can view all code..i only bind the drop-down related value, by clicking on edit button within table, its not working within drop-down
<table st-table="sub" st-safe-src="subcate" class="table table-striped">
<thead>
<tr>
<th style="color:black">Id</th>
<th style="color:black" width="100px">SubCatagoryName</th>
<th style="color:black" width="100px">CatagoryName</th>
<th style="color:black">Action</th>
</tr>
<tr>
<th colspan="5">
<label>Search..</label>
<input st-search placeholder="search" class="input-sm form-control" type="search" />
</th>
</tr>
</thead>
<tbody>
<tr st-select-row="row" st-select-mode="multiple" ng-repeat="row in sub">
<td style="color:black">{{row.Id}}</td>
<td style="color:black">{{row.SubCataName}}</td>
<td style="color:black">{{row.tblcatagory.CataName}}</td>
<td>
<div class="btn-group" role="group" aria-label="...">
<button type="button" class="btn btn-default" ng-click="subcateedit(row.Id)">
<i class="glyphicon glyphicon-pencil" style="color:black">
</i>
</button>
<button type="button" class="btn btn-danger" ng-click="subcatedelete(row.Id)">
<i class="glyphicon glyphicon-trash" style="color:white">
</i>
</button>
</div>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="5" class="text-center">
<div st-pagination="" st-items-by-page="itemsByPage"></div>
</td>
</tr>
</tfoot>
</table>
html form code:
<section class="panel">
<header class="panel-heading danger">
Add Catagory
</header>
<div class="panel-body" ng-controller="DemoCtrl">
<div ng-form="frm" name="loginForm"
class="pure-form pure-form-aligned" autocomplete="off">
<div class="position-center">
<div class="form-group" ng-class="{ 'has-error' :loginForm.ddl.$invalid && !loginForm.ddl.$pristine }">
<label>SubCatagory Name*</label>
<p>{{ SubCata.tblcatagory.CataName }}</p>
<select required name="ddl"
value="{{ SubCata.tblcatagory.CataName }}"
class="form-control"
ng-model="SubCata"
ng-options="item.CataName for item in cate">
</select>
<p ng-show="loginForm.ddl.$dirty && loginForm.ddl.$error.required"
class="help-block">Catagory Name is required</p>
</div>
<div class="form-group" ng-class="{ 'has-error' :loginForm.name.$invalid && !loginForm.name.$pristine }">
<label>SubCatagory Name*</label>
<input type="text" name="name" class="form-control" ng-model="SubCata.SubCataName"
ng-minlength="3" ng-maxlength="20" required>
<p ng-show="loginForm.name.$dirty && loginForm.name.$error.required"
class="help-block">SubCatagory Name is required</p>
<p ng-show="loginForm.name.$error.minlength" class="help-block">
SubCatagory Name is too short.
</p>
<p ng-show="loginForm.name.$error.maxlength" class="help-block">
SubCatagory Name is too long.
</p>
</div>
<button type="submit" class="btn btn-primary" ng-click="submitSubForm(loginForm.$valid , SubCata)"
ng-disabled="loginForm.$invalid">
Submit
</button>
</div>
</div></div>
</section>
UPDATE
now one issue is that ng-model="SubCata.tblcatagory.CataName" due to this i can't get the this {{SubCata.tblcatagory.Id}} id in the controller $scope
<select required name="ddl" class="form-control"
ng-model="SubCata.tblcatagory.Id"
ng-options="item.Id as item.CataName for item in cate">
</select>
i get id from this code
<label>SubCatagory Name*</label>
<p>{{ SubCata.tblcatagory.CataName }}</p>
<select required name="ddl"
value="{{ SubCata.tblcatagory.CataName }}"
class="form-control"
̶n̶g̶-̶m̶o̶d̶e̶l̶=̶"̶S̶u̶b̶C̶a̶t̶a̶"̶
̶n̶g̶-̶o̶p̶t̶i̶o̶n̶s̶=̶"̶i̶t̶e̶m̶.̶C̶a̶t̶a̶N̶a̶m̶e̶ ̶f̶o̶r̶ ̶i̶t̶e̶m̶ ̶i̶n̶ ̶c̶a̶t̶e̶"̶
ng-model="SubCata.tblcatagory.CataName"
ng-options="item.CataName as item.CataName for item in cate">
</select>

How to push JSON object to array using single AngularJS controller

Please guide me how do I push a new commodity object in the above loads object, by submiting a new form for commodity. The code I have tried is given below.
Note when I fill the form of commodity and submit to push in above json, it tells me undefined for loads.commodities.push
I have a complete sample JSON object (we call it loads), In which I have to push a commodity object. For new commodity I have an explicit form to add a new commodity details and push into existing loads object.
Loads Object:
{
"loadStops": [
{
"companyId": 148,
"companyCode": null,
"legalName": "Frontier WHSE",
"accessorialReason": null,
"commodities": [{
"id": 1,
"commodity": "Food",
"estWeight": 20000.00
}]
}
]
}
Display Table for viewing the loads data and Form to add New Commodity
<div ng-controller="FreightSaleCtrl">
<table>
<tr>
<th> Company Code </th> <th> Legal Name </th>
</tr>
<tr ng-repeat="theLoad in loads">
<td> {{theLoad.companyCode}} </td>
<td> {{theLoad.legalName}} </td>
</tr>
<tr>
<td colspan="2">
<table>
<tr>
<th> Commodity </th> <th> EstWeight </th>
</tr>
<tr ng-repeat="cmdty in theLoad.commodities">
<td> cmdty.commodity </td>
<td> cmdty.estWeight </td>
</tr>
</table>
</td>
</tr>
</table>
</div>
<div>
<form ng-controller="FreightSaleCtrl">
<input type="text" ng-model="commodityForm.commodity"/>
<input type="text" ng-model="commodityForm.estWeight"/>
<input type="submit" value="Add New Commodity"/>
</form>
</div>
My AngularJS controller:
(function() {
'use strict';
angular.module('bootstrapApp').controller('FreightSaleCtrl', FreightSaleCtrl);
function FreightSaleCtrl($scope, $location, $http, $compile) {
$scope.loads[0].commodities.push( $scope.commodityForm );
}
});
My new commodity form that opens by clicking on the link given in the commodity table:**
<div class="modal fade" id="commoditiesModal" tabindex="-1" role="dialog"
aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg" role="document">
<form ng-controller="FreightSaleCtrl" id="commodity-form" role="form" novalidate>
<div class="modal-content">
<div class="modal-header modal-lg">
<h5 class="modal-title" id="exampleModalLabel">
Add Commodity
<button type="button" class="close" data-dismiss="modal"
aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</h5>
</div>
<div class="modal-body">
<div class="row"> <!-- row-1 -->
<div class="col-sm-3"> <!-- [0, 0] -->
<fieldset class="form-group">
<label id="fieldTitle">Commodity</label>
<input type="text" class="form-control" placeholder="" required data-error="Commodity required">
<div class="help-block with-errors"></div>
</fieldset>
</div>
<div class="col-sm-3"> <!-- [0, 1] -->
<fieldset class="form-group">
<label id="fieldTitle">Est. Weight</label>
<input type="text" class="form-control" placeholder="" required data-error="Est. weight required">
<div class="help-block with-errors"></div>
</fieldset>
</div>
</div>
</div>
<div class="modal-footer">
<input type="reset" class="btn btn-warning btn-sm" value="Reset" />
<button type="button" class="btn btn-danger btn-sm" ng-click="clear()"
data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-default btn-sm">
<i class="fa fa-check-square-o"></i> Submit
</button>
</div>
</div>
</form>
</div>
</div>
The above form opens, when I click on this button: while the commodities displayed in the table:
The Commodity Form Modal itself
Every time the controller is specified, it will create new instance
of that controller So it should be kept inside one controller
theLoad.commodities cannot be accessed as it is ouside the
<tr ng-repeat="cmdty in theLoad.commodities">
<td> cmdty.commodity </td>
<td> cmdty.estWeight </td>
</tr>
One way to solve this is to have add input boxes inside the table - for each loads
<!DOCTYPE html>
<html>
<head>
<script data-require="jquery#3.0.0" data-semver="3.0.0" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.js"></script>
<link data-require="bootstrap#3.3.7" data-semver="3.3.7" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />
<script data-require="angular.js#1.6.6" data-semver="1.6.6" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular.min.js"></script>
<script src="https://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-2.5.0.min.js"></script>
<script>
(function() {
var app = angular.module("bootstrapApp", ['ui.bootstrap']);
app.component('modalComponent', {
templateUrl: 'myModalContent.html',
bindings: {
resolve: '<',
close: '&',
dismiss: '&'
},
controller: function($scope) {
var $ctrl = this;
$ctrl.$onInit = function() {
$scope.theLoad = $ctrl.resolve.currentLoad;
};
$scope.ok = function() {
$ctrl.close({
$value: $scope.theLoad
});
};
}
});
app.controller('FreightSaleCtrl', ['$scope', '$uibModal', function($scope, $uibModal) {
$scope.loads = [{
"companyId": 148,
"companyCode": 1234,
"legalName": "Frontier WHSE",
"accessorialReason": null,
"commodities": [{
"id": 1,
"commodity": "Food",
"estWeight": 20000.00
}, {
"id": 2,
"commodity": "Another",
"estWeight": 160000.00
}]
}, {
"companyId": 45,
"companyCode": 7879,
"legalName": "ASD froads",
"accessorialReason": null,
"commodities": [{
"id": 10,
"commodity": "Drinks",
"estWeight": 5600.00
}]
}];
$scope.openModal = function(load) {
var modalInstance = $uibModal.open({
animation: true,
component: 'modalComponent',
resolve: {
currentLoad: function() {
return load;
}
}
}).result.then(function(currentLoad) {
if (currentLoad) {
var maxValue = Math.max.apply(Math, currentLoad.commodities.map(function(o) {
return o.id;
}))
if (!maxValue) {
maxValue = 0;
}
currentLoad.newCommodity.id = maxValue + 1;
currentLoad.commodities.push(angular.copy(currentLoad.newCommodity));
currentLoad.newCommodity = undefined;
}
}, function() {
console.log('modal-component dismissed at: ' + new Date());
});
};
}]);
}());
</script>
<style></style>
</head>
<body ng-app="bootstrapApp">
<div ng-controller="FreightSaleCtrl">
<script type="text/ng-template" id="myModalContent.html">
<div class="modal-header">
<h3 class="modal-title" id="modal-title">Add Commodity !</h3>
</div>
<div class="modal-body" id="modal-body">
<form name="testForm">
<div class="form-group" ng-class="{ 'has-error' : testForm.commodity.$invalid && !testForm.commodity.$pristine }">
<label>Commodity</label>
<input type="text" name="commodity" ng-model="theLoad.newCommodity.commodity" placeholder="Commodity" ng-minlength="3" ng-maxlength="8" required/>
<p ng-show="testForm.commodity.$error.required && !testForm.commodity.$pristine" class="help-block">commodity is required.</p>
<p ng-show="testForm.commodity.$error.minlength" class="help-block">commodity is too short.</p>
<p ng-show="testForm.commodity.$error.maxlength" class="help-block">commodity is too long.</p>
</div>
<div class="form-group" ng-class="{ 'has-error' : testForm.estWeight.$invalid && !testForm.estWeight.$pristine }">
<label>estWeight</label>
<input type="text" name="estWeight" ng-model="theLoad.newCommodity.estWeight" placeholder="EST Weight" ng-minlength="3" ng-maxlength="8" required/>
<p ng-show="testForm.estWeight.$error.required && !testForm.estWeight.$pristine" class="help-block">estWeight is required.</p>
<p ng-show="testForm.estWeight.$error.minlength" class="help-block">estWeight is too short.</p>
<p ng-show="testForm.estWeight.$error.maxlength" class="help-block">estWeight is too long.</p>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-primary" type="button" ng-click="ok()">OK</button>
<button class="btn btn-warning" type="button" ng-click="cancel()">Cancel</button>
</div>
</form>
</script>
<form name="commonForm">
<table class="table">
<tr>
<th> Company Code </th>
<th> Legal Name </th>
<th> Commodity </th>
<th> EstWeight </th>
</tr>
<tr ng-repeat="theLoad in loads">
<td> {{theLoad.companyCode}} </td>
<td> {{theLoad.legalName}} </td>
<td colspan="2">
<table class="table">
<tr ng-repeat="cmdty in theLoad.commodities track by cmdty.id">
<td>{{cmdty.id}} {{cmdty.commodity}} </td>
<td> {{cmdty.estWeight}} </td>
</tr>
<tr>
<td colspan="2">
<input class="pull-right" type="button" value="Add" ng-click="openModal(theLoad)" />
</td>
</tr>
</table>
</td>
</tr>
</table>
</form>
</div>
</body>
</html>

Custom filter angular on ng-repeat for stike text if disabled

I'd like to add a custom filter on my angularJS app. I want di strike text like this way if the object in the ng-repat has the isDeleted flag set as true. Code: here the HTML:
<table id="tableText" class="table table-hover table-striped" ng-init="allNews()">
<tr>
<th>Titolo</th>
<th>Text</th>
<th>Disattivato</th>
<th>Modifica</th>
<th ng-if="!cancelDelete">Elimina</th>
<th ng-if="cancelDelete">Annulla</th>
</tr>
<tr ng-repeat="news in allNews | filter: deleteTitleText(news)">
<td>
<div ng-hide="editingData[news.id]">{{ news.title }}</div>
<div ng-show="editingData[news.id]"><input type="text" class="form-control" ng-model="news.title" /></div>
</td>
<td>
<div ng-hide="editingData[news.id]">{{ news.arg }}</div>
<div ng-show="editingData[news.id]"><input type="text" class="form-control" ng-model="news.arg" /></div>
</td>
<td>
<div ng-hide="editingData[news.id]"><input type="checkbox" disabled ng-model="news.isDeleted"></div>
<div ng-show="editingData[news.id]"><input type="checkbox" ng-model="news.isDeleted"></div>
</td>
<td>
<div ng-hide="editingData[news.id]"><button id="modify" class="btn btn-primary" ng-click="modify(news, $event)">Modifica</button></div>
<div ng-show="editingData[news.id]"><button id="accept" class="btn btn-success" ng-click="update(news)">Accetta</button></div>
</td>
<td>
<div ng-hide="editingData[news.id]"><button id="delete" class="btn btn-danger" ng-click="delete(news.id)">Cancella</button></div>
<div ng-show="editingData[news.id]"><button id="cancel" class="btn btn-danger" ng-click="cancelModify()">Annulla</button></div>
</td>
</tr>
</table>
The JS:
app.filter('deleteTitleText', function () {
return function (news) {
if (news.isDeleted == true) {
news.title = "<span><del>" + news.title + "</del></span>";
news.arg = "<span><del>" + news.arg + "</del></span>";
}
return news;
}
});
This is a good way to implement this kind of filter? For now I receive this error: angular.js:13920 Error: [filter:notarray] Expected array but received: function (). Thanks
OPTION 1:
<table id="tableText" class="table table-hover table-striped" ng-init="allNews()">
<tr>
<th>Titolo</th>
<th>Text</th>
<th>Disattivato</th>
<th>Modifica</th>
<th ng-if="!cancelDelete">Elimina</th>
<th ng-if="cancelDelete">Annulla</th>
</tr>
<tr ng-repeat="news in allNews">
<td>
<div ng-hide="editingData[news.id]">
<span ng-hide="news.isDeleted">{{ news.title }}</span>
<span ng-show="news.isDeleted"><del>{{ news.title }}</del></span>
<!-- USING ng-if -->
<!--
<span ng-if="!news.isDeleted">{{ news.title }}</span>
<span ng-if="news.isDeleted"><del>{{ news.title }}</del></span>
-->
</div>
<div ng-show="editingData[news.id]"><input type="text" class="form-control" ng-model="news.title" /></div>
</td>
<td>
<div ng-hide="editingData[news.id]">
<span ng-hide="news.isDeleted">{{ news.arg }}</span>
<span ng-show="news.isDeleted"><del>{{ news.arg }}</del></span>
<!-- USING ng-if -->
<!--
<span ng-if="!news.isDeleted">{{ news.arg }}</span>
<span ng-if="news.isDeleted"><del>{{ news.arg }}</del></span>
-->
</div>
<div ng-show="editingData[news.id]"><input type="text" class="form-control" ng-model="news.arg" /></div>
</td>
<td>
<div ng-hide="editingData[news.id]"><input type="checkbox" disabled ng-model="news.isDeleted"></div>
<div ng-show="editingData[news.id]"><input type="checkbox" ng-model="news.isDeleted"></div>
</td>
<td>
<div ng-hide="editingData[news.id]"><button id="modify" class="btn btn-primary" ng-click="modify(news, $event)">Modifica</button></div>
<div ng-show="editingData[news.id]"><button id="accept" class="btn btn-success" ng-click="update(news)">Accetta</button></div>
</td>
<td>
<div ng-hide="editingData[news.id]"><button id="delete" class="btn btn-danger" ng-click="delete(news.id)">Cancella</button></div>
<div ng-show="editingData[news.id]"><button id="cancel" class="btn btn-danger" ng-click="cancelModify()">Annulla</button></div>
</td>
</tr>
</table>
OPTION 2:
<span ng-bind-html="news | deleteTitleText"></span>
app.filter('deleteTitleText', function ($sce) {
return function (input) {
if(input.isDeleted) {
output = $sce.trustAsHtml("<del>"+input.title+"</del>");
} else {
output = $sce.trustAsHtml("<span>"+input.title+"</span>");
}
return output;
};
});
remove filter from ng-repeat <tr ng-repeat="news in allNews">
So final would be similar to :
<tr ng-repeat="news in allNews">
<td>
<div ng-hide="editingData[news.id]">
<span ng-bind-html="news | deleteTitleText"></span>
</div>
<div ng-show="editingData[news.id]"><input type="text" class="form-control" ng-model="news.title" /></div>
</td>
....
....
Hope this helps
You need to alter you filter to expect the entire allNews array/object and work with that instead of just a single item in the list.
This might help.
For instance:
app.filter('deleteTitleText', function () {
return function (allNews) {
var filtered = [];
angular.forEach(allNews, function(news) {
if (news.isDeleted == true) {
news.title = "<span><del>" + news.title + "</del></span>";
news.arg = "<span><del>" + news.arg + "</del></span>";
}
filtered.push(news);
});
return filtered;
}
});
Your ng-repeat should be changed from:
ng-repeat="news in allNews | filter: deleteTitleText(news)"
To:
ng-repeat="news in allNews | deleteTitleText"
Try to use ng-style, like in this plunker: https://plnkr.co/edit/0koMSQ54gUChdpB4Vrrm?p=preview
!item.isDisabled ? {'text-decoration': 'line-through'} : {'text-decoration': 'none'}
You can simply use ng-show and ng-hide
<tr ng-repeat="news in allNews">
<span ng-show="news.isDeleted"><del>{{news.title}}</del></span>
<span ng-show="news.isDeleted"><del>{{news.arg}}</del></span>
<span ng-hide="news.isDeleted"><del>{{news.title}}</del></span>
<span ng-hide="news.isDeleted"><del>{{news.arg}}</del></span>
.
.
.
</tr>

AngularJS Service not calling controller to get updated data after CRUD operation

I am beginner in AngularJS and trying to create a master data entry screen, where upper portion containing form fields & lower portion containing table(GridView) to display all master entries. Grid showing all the data when i initially run the application. If i add/Edit any new/old records, the updated data not reflected in the gridview. (i.e) If i add any new entry, it is saving into the DB through service, but not reflecting in the GridView. Even if i navigate through menu also not displaying the updated data in the grid. But if i press Ctrl + F5, it is showing updated data in the Grid. Alsp If i close the browser & re run the application then the updated records displaying in the Gridview. Below is my code. Please help.. Thank you.!
Index.cshtml
<div class="row">
<div class="col-md-12">
<h3 class="page-header">
Component Master
</h3>
<div class="col-md-12">
<div class="alert alert-dismissible alert-danger" ng-show="ComponentForm.$invalid && submitted">
<button type="button" class="close" aria-hidden="true" data-dismiss="alert">
×</button>
<p ng-show="ComponentForm.ComponentName.$error.required && (ComponentForm.ComponentName.$dirty || submitted)">
- Component Name is required.</p>
<p ng-show="ComponentForm.ComponentName.$error.minlength && (ComponentForm.ComponentName.$dirty || submitted)">
- Component Name should be minimum 5 char long.</p>
<p ng-show="ComponentForm.Language.$error.required && (ComponentForm.Language.$dirty || submitted)">
- Language Selection is required.</p>
</div>
</div>
<div class="col-md-12">
<div class="panel panel-success">
<div class="panel-heading">
<h3 class="panel-title">
Panel success</h3>
</div>
<div class="panel-body">
<div class="row">
<div class="col-lg-12">
<!-- FORM : YOU CAN DISABLE, HTML5 VALIDATION BY USING "novalidate" ATTRIBUTE-->
<form name="ComponentForm" class="form-inline" novalidate>
<!-- COMPONENT NAME -->
<div class="form-group" ng-class="{ 'has-error' : ComponentForm.ComponentName.$invalid && (ComponentForm.ComponentName.$dirty || submitted) }"
style="margin: 10px;">
<label style="margin-right: 10px;">
Component Name</label>
<input type="text" name="ComponentName" ng-model="ComponentModel.ComponentName" class="form-control"
placeholder="Component Name..." ng-minlength="5" ng-required="true" />
<input type="hidden" data-ng-model="ComponentModel.ComponentID" />
<input type="hidden" data-ng-model="ComponentModel.IsActive" />
<input type="hidden" data-ng-model="UserID" />
</div>
<!-- LANGUAGE -->
<div class="form-group" style="margin: 10px;" ng-class="{ 'has-error' : ComponentForm.Language.$invalid && (ComponentForm.Language.$dirty || submitted) }">
<label style="margin-right: 10px;">
Language</label>
<select name="Language" data-ng-model="ComponentModel.Language" class="form-control"
ng-required="true">
<option value="" title="Select">Select</option>
<option value="English" title="English">English</option>
<option value="Spanish" title="Spanish">Spanish</option>
</select>
</div>
<!-- ng-disabled FOR ENABLING AND DISABLING SUBMIT BUTTON -->
<!-- SAVE BUTTON -->
#*<button type="submit" class="btn btn-info" ng-disabled="ComponentForm.$invalid" value="Add">Add</button>*#
<button type="submit" class="btn btn-primary" ng-click="SaveComponent(ComponentModel);"
ng-value="Add">
Add
</button>
<button type="submit" class="btn btn-warning" ng-click="ClearComponent();" value="Clear">
Clear
</button>
</form>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-12">
<table class="table table-striped table-bordered table-hover">
<thead>
<tr class="success">
<th class="text-center">
ComponentID
</th>
<th class="text-center">
Component Name
</th>
<th class="text-center">
Language
</th>
<th class="text-center">
IsActive
</th>
<th class="text-center">
Last Modified By
</th>
<th class="text-center">
Last Modified Date
</th>
<th class="text-center">
Action
</th>
</tr>
<tr style="height: 250px; border: 2px solid #ecf0f1;" data-ng-show="ShowEmptyRow">
<th colspan="7" class="text-center" style="vertical-align: middle;">
<label class="control-label">
No Records Found.</label>
</th>
</tr>
</thead>
<tbody>
<tr data-ng-repeat="Component in ComponentMaster" data-ng-show="!ShowEmptyRow" ng-class="{'danger':!Component.IsActive}">
<td style="vertical-align: middle; text-align: center;">
{{ Component.ComponentID}}
</td>
<td style="vertical-align: middle;">
{{ Component.ComponentName}}
</td>
<td style="vertical-align: middle;">
{{ Component.Language}}
</td>
<td style="vertical-align: middle; text-align: center;">
<div class="checkbox">
<label>
<input type="checkbox" disabled="disabled" ng-checked="Component.IsActive" /></label>
</div>
</td>
<td style="vertical-align: middle;">
{{ Component.ModifiedBy}}
</td>
<td style="vertical-align: middle; text-align: center;">
{{ Component.ModifiedDate}}
</td>
<th style="vertical-align: middle; text-align: center;">
<span class="btn btn-info btn-sm" ng-show="Component.IsActive" ng-click="EditComponent(Component.ComponentID);">
Edit</span> <span class="btn btn-danger btn-sm" ng-show="Component.IsActive" ng-click="ActivateDeActivateComponent(Component.ComponentID,false,ComponentModel.ModifiedBy);">
Delete</span> <span class="btn btn-info btn-sm" ng-show="!Component.IsActive" ng-click="ActivateDeActivateComponent(Component.ComponentID,true,ComponentModel.ModifiedBy);">
Activate</span>
</th>
</tr>
</tbody>
</table>
</div>
</div>
</div>
Angular Script:
var AngularApp = angular.module("AngularApp", ['ngRoute']);
AngularApp.controller("ConfigurationController", ['$scope', 'ConfigurationService', function ($scope, ConfigurationService) {
$scope.ComponentMaster = [];
GetComponentMasterDetails();
/*------------- Save Component ---------------- */
// When i click Save btn - executing this function. control comes here...
$scope.SaveComponent = function (ComponentModel) {
$scope.submitted = true;
if ($scope.ComponentForm.$valid) {
ComponentModel.ModifiedBy = $scope.UserID;
// control comes here... & Calling method "SaveComponentMaster" inside ConfigurationService & returned execution message
var Msg = ConfigurationService.SaveComponentMaster(ComponentModel);
Msg.then(function (response) {
if (response.data != "") {
alert(response.data);
}
else {
// After Saved into DB showing below alert message.
alert("Data Saved Successfully.");
// Calling below method to get the updated records from DB
GetComponentMasterDetails();
}
}, function (error) {
alert(error.data);
});
}
else {
alert("Please correct errors!");
}
}
/**----------------------------------------------------- */
// Below method is calling...
function GetComponentMasterDetails() {
// Call moves to ConfigurationService Service method...
var ComponentMaster = ConfigurationService.GetComponentMasterDetails();
ComponentMaster.then(function (response) {
if (response.data != "") {
// This service call returning the old data only.
// Updated/Added entry details not reflecting in the returned object.
// This is the reason why it is showing old records only in the Grid.
$scope.ShowEmptyRow = false;
$scope.ComponentMaster.length = 0;
angular.extend($scope.ComponentMaster, response.data);
}
else {
$scope.ShowEmptyRow = true;
$scope.ComponentMaster.length = 0;
}
}, function (error) {
alert(error.data);
});
}
} ]);
AngularApp.service("ConfigurationService", function ($http) {
// Call comes here...
this.GetComponentMasterDetails = function () {
// Call comes here... But this $http.get - not calling MVC controller Action method.
// I kept my breakpoint in MVC controller method, but not executed the method.
// So this Service just returning old records. This is the reason the View showing old records.
// If i press Ctrl + F5, it is calling MVC controller message & showing the updated records.
return $http.get('/Configuration/GetComponentMasterDetails');
};
// Control comes here... Then calling MVC controller Action method.. Saving data into DB & returned execution message.
this.SaveComponentMaster = function (ComponentModel) {
var response = $http({
method: 'POST',
url: '/Configuration/SaveComponentMaster/',
data: { ComponentModel: ComponentModel }
});
return response;
};
});
MVC Controller
[NoCache]
[HttpGet]
public ActionResult GetComponentMasterDetails()
{
RNDDBContext dbContext = new RNDDBContext();
var result = dbContext.ExecuteStoreQuery<ComponentModel>("exec PROC_GET_COMPONENT_MASTER_DETAILS").ToList();
return Json(result, JsonRequestBehavior.AllowGet);
}
[NoCache]
[HttpPost]
public JsonResult SaveComponentMaster(ComponentModel ComponentModel)
{
RNDDBContext dbContext = new RNDDBContext();
var result = dbContext.ExecuteStoreQuery<string>("exec PROC_SAVE_COMPONENT_MASTER #ComponentID,#ComponentName,#Language,#IsActive,#ModifiedBy",
new SqlParameter("ComponentID", ComponentModel.ComponentID),
new SqlParameter("ComponentName", ComponentModel.ComponentName),
new SqlParameter("Language", ComponentModel.Language),
new SqlParameter("IsActive", ComponentModel.IsActive),
new SqlParameter("ModifiedBy", ComponentModel.ModifiedBy)
).FirstOrDefault();
return Json(result, JsonRequestBehavior.AllowGet);
}
public class NoCache : ActionFilterAttribute
{
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
filterContext.HttpContext.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
filterContext.HttpContext.Response.Cache.SetValidUntilExpires(false);
filterContext.HttpContext.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
filterContext.HttpContext.Response.Cache.SetNoStore();
base.OnResultExecuting(filterContext);
}
}
Initialize your $scope.ComponentMaster on the top of controller
AngularApp.controller("ConfigurationController", ['$scope', 'ConfigurationService', function ($scope, ConfigurationService) {
$scope.ComponentMaster = [];
GetComponentMasterDetails();
and just empty that, then repopulate once you call GetComponentMasterDetails()
function GetComponentMasterDetails() {
var ComponentMaster = ConfigurationService.GetComponentMasterDetails();
ComponentMaster.then(function (response) {
if (response.data != "") {
$scope.ShowEmptyRow = false;
// Empty the ComponentMaster array
$scope.ComponentMaster.length = 0;
// Add the retrieved data
angular.extend($scope.ComponentMaster, response.data)
}
else {
$scope.ShowEmptyRow = true;
// Empty the ComponentMaster array
$scope.ComponentMaster.length = 0;
}
}, function (error) {
alert(error.data);
});
}
This issue is similar to this

Uncaught TypeError: Cannot read property 'file' of undefined(…)

I am trying to upload an image from my html an on click of save button, i am calling an upload function in the controller. When i enter the upload function in controller, i am not able to access $scope to check the $scope.file.name.
//upload image.html
<div class="horizontal">
<table border=1 frame=void rules=rows class="ui celled table" >
<thead style="text-align: center;">
<tr>
<th> Id </th>
<th> Question </th>
<th> Option A </th>
<th> Option B </th>
<th> Option C </th>
<th> Option D </th>
<th> Answer </th>
<th> Section id </th>
<th> Image </th>
<th> Edit</th>
</tr></thead>
<tbody ng-repeat="ques in questionObj | filter: searchText" style="text-align: center;">
<tr>
<td>{{$index + 1}}</td>
<td><span ng-show="editEnabled" ng-model="Title">
{{ ques.Title || 'empty' }}
</span>
<div ng-hide="editEnabled">
<textarea ng-model="ques.Title"></textarea>
</div>
</td>
<td><span ng-show="editEnabled" ng-model="Title">{{ques.Option_a || 'empty'}} </span>
<div ng-hide="editEnabled" class="option">
<textarea ng-model="ques.Option_a"></textarea>
</div>
</td>
<td><span ng-show="editEnabled" ng-model="Title">{{ques.Option_b || 'empty'}} </span>
<div ng-hide="editEnabled" class="option">
<textarea ng-model="ques.Option_b"></textarea>
</div>
</td>
<td><span ng-show="editEnabled" ng-model="Title">{{ques.Option_c || 'empty'}} </span>
<div ng-hide="editEnabled" class="option">
<textarea ng-model="ques.Option_c"></textarea>
</div>
</td>
<td><span ng-show="editEnabled" ng-model="Title">{{ques.Option_d || 'empty'}} </span>
<div ng-hide="editEnabled" class="option">
<textarea ng-model="ques.Option_d"></textarea>
</div>
</td>
<td><span ng-show="editEnabled" ng-model="Title">{{ques.Answer || 'empty'}} </span>
<div ng-hide="editEnabled" class="option">
<textarea ng-model="ques.Answer"></textarea>
</div>
</td>
<td><span ng-show="editEnabled" ng-model="Title">{{ques.Section_id || 'empty'}} </span>
<div ng-hide="editEnabled" class="option">
<input type="text" ng-model="ques.Section_id"></input>
</div>
</td>
<td>
<span ng-if="ques.Image != 'nil'" ng-show="editEnabled" ng-model="Title"> <img ng-src="{{ques.Image}}" class="image-container" /></span>
<span ng-if="ques.Image === 'nil'" ng-show="editEnabled" ng-model="Title">No Image</span>
<div ng-if="ques.Image != 'nil'" ng-hide="editEnabled" class="option">
<img ng-src="{{ques.Image}} " class="image-container" />
</div>
<div ng-if="ques.Image === 'nil'" ng-hide="editEnabled" class="option">
<input class="bottom-marg-15" type="file" name="file" file onchange="angular.element(this).scope().imageLoad(this)"></input>
<!-- Progress Bar -->
<div class="progress">
<div class="progress-bar" role="progressbar" aria-valuenow="{{ uploadProgress }}" aria-valuemin="0" aria-valuemax="100" style="width: {{ uploadProgress }}%;">
{{ uploadProgress == 0 ? '' : uploadProgress + '%' }}
</div>
</div>
<div ng-repeat="step in stepsModel">
<img class="small-thumb" ng-src="{{step}}" />
</div>
</div>
</td>
<td style="white-space: nowrap">
<div class="buttons" ng-show="editEnabled" ng-show="editEnabled">
<button class="btn btn-primary" ng-click="editEnabled = !editEnabled">edit</button>
<button class="btn btn-danger" ng-click="question.removeUser($index,ques.Id)">del</button>
</div>
<div ng-hide="editEnabled" class="form-buttons form-inline">
<button ng-model="Title" ng-disabled="editQuestionForm.$waiting" ng-click=" upload(); editEnabled = !editEnabled" class="btn btn-primary">
save
</button>
<button type="button" ng-click="editEnabled = !editEnabled" class="btn btn-default">
cancel
</button>
</div>
</td>
</tr>
</tbody>
this is the controller which has the upload function. I am not able to access $scope inside upload function.
'use strict';
angular.module('onlineTestAngularApp')
.controller('editQuestionCtrl', function($scope, GetQuestionsService, $window, $location, localStorageService, ENV) {
var vm = this;
vm.success = false;
vm.auth_token = localStorageService.get('rec-auth-token');
vm.role = localStorageService.get('role');
$scope.editEnabled = true;
$scope.access_key = ENV.access_key;
$scope.secret_key = ENV.secret_key;
$scope.bucket = "q-auth/angular_test/";
$scope.stepsModel = [];
$scope.imageLoad = function(element){
var reader = new FileReader();
reader.onload = $scope.imageIsLoaded;
reader.readAsDataURL(element.files[0]);
}
$scope.imageIsLoaded = function(e){
$scope.$apply(function() {
$scope.stepsModel.push(e.target.result);
});
}
$scope.upload = function($scope){
console.log("inside upload");
}
});
Your upload() is having a parameter called $scope, remove it.
Change:
$scope.upload = function($scope){
console.log("inside upload");
}
To:
$scope.upload = function(){
console.log("inside upload");
};
Because when you call the function upload() it will expect to pass an argument, $scope in the function is taken as local variable of that function, hence becoming undefined.
Once you enter the controller's function you have access to its $scope. There's no need to pass it as a parameter:
Controller
$scope.upload = function() {
console.log($scope.stepsModel) // or any other property
}
It seems you mix two techniques for accessing controller's scope: vm and $scope. My advice is to use vm only for exposing the controller variables to the view. Using $scope will soon be deprecated and I use it mainly for $watching changes in the view.

Resources