How to Send multiple values from Asp.Net WebApi to Angularjs Controller? - angularjs

WebApi Controller.. How to send this value to Angularjs controller (bill = q.TotalBill;)? I have send this (return Ok(gridlist);) into JSON form into angularjs controller
public static double bill; // this is static variable on top of a class
[System.Web.Http.Route("api/Products/gridpro/{id}")]
public IHttpActionResult GetGrid(int id)
{
var q = db.products.Find(id);
if (q != null)
{
var check = gridlist.Where(x => x.Id == id).FirstOrDefault();
if (check != null)
{
check.ProductQty += 1;
check.TotalAmount = check.ProductQty * check.ProductRate;
}
else
{
q.ProductQty = 1;
q.TotalAmount = q.ProductQty * q.ProductRate;
gridlist.Add(q);
}
q.TotalBill = gridlist.Sum(x => x.TotalAmount);
foreach (var item in gridlist)
{
item.TotalBill = q.TotalBill;
}
bill = q.TotalBill; //How to send this value to Angularjs controller
return Ok(gridlist);
}
else
{
return NotFound();
}
}
Anagularjs Code: I see all the data into the HTML using this ($scope.gridproducts) but I want to show (bill = q.TotalBill;) this single value into HTML code
$scope.OnProChange = function (Pro) {
var id = Pro.Id;
$http.get("/api/Products/gridpro/" + id).then(function (response) {
console.log(JSON.stringify(response.data))
$scope.gridproducts = response.data;
})
}
HTML code:How I can show total bill value I use {{gridproducts.TotalBill}} this but nothing works.
<tbody>
<tr ng-repeat="item in gridproducts">
<td>
<a class="delete"><i class="fa fa-times-circle-o"></i></a>
</td>
<td class="name">{{item.ProductName}}</td>
<td>{{item.ProductRate}}</td>
<td>
<input class="form-control qty" style="width:50px" onchange="UpdatePurchaseItem('36',this.value)" value="{{item.ProductQty}}">
</td>
<td>{{item.TotalAmount}}</td>
</tr>
<tr></tr>
<tfoot>
<tr>
<th colspan="2"></th>
<th colspan="2"><b>Total</b></th>
<th><b>{{gridproducts.TotalBill}}</b></th>
</tr>
<tr>
<th colspan="2"><b></b></th>
<th colspan="2"><b>Total Items</b></th>
<th><b>25</b></th>
</tr>
</tfoot>
</tbody>

if you want send multiple values to angularjs , you may create complex type for that.
for example,
in c# code
Public Class GridDataModel<T>
{
public T ItemList{get;set;}
public int TotalBill{get;set}
}
then when you return data to js
var gridData=new GridDataModel<products>()
{
ItemList=gridlist,
TotalBill=q.TotalBill
}
return Ok(gridData);
after doing this , you can create another propert for js scope
$http.get("/api/Products/gridpro/" + id).then(function (response) {
console.log(JSON.stringify(response.data))
$scope.gridproducts = response.data.ItemList;
$scope.totalBill = response.data.TotalBill;
})

Related

Generated password using angular js not working

I want to make the password is auto generated and to pass it to the controller :
this is my view.jsp:
<tr>
<td class="leftDetails">Password</td>
<td class="rightDetails"><input type="text" name="password" ng-model="newUser.password" ng-disabled="isEditMode" id="p"/></td>
<td class="rightDetails"><input type='button' value ='generate' onclick='document.getElementById("p").value = Password.generate(16)' ng-show="add"></td>
<td class="leftDetails"></td>
<td class="rightDetails"></td>
</tr>
<script>
var Password = {
_pattern : /[a-zA-Z0-9_\-\+\.]/,
_getRandomByte : function()
{
if(window.crypto && window.crypto.getRandomValues)
{
var result = new Uint8Array(1);
window.crypto.getRandomValues(result);
return result[0];
}
else if(window.msCrypto && window.msCrypto.getRandomValues)
{
var result = new Uint8Array(1);
window.msCrypto.getRandomValues(result);
return result[0];
}
else
{
return Math.floor(Math.random() * 256);
}
},
generate : function(length)
{
return Array.apply(null, {'length': length})
.map(function()
{
var result;
while(true)
{
result = String.fromCharCode(this._getRandomByte());
if(this._pattern.test(result))
{
return result;
}
}
}, this)
.join('');
}
};
My problem is want to pass the generated password to my controller ,it was empty
How to correct that. thanks in advance?
The angular way to solve this issue is to update your input ng-model instead of selecting the element (Jquery way).
Instead of onClick use ng-click="newUser.password = Password.generate(16)"

Checkbox checked not updating on delete, its updating the second time

i have a code like this:
<body ng-app="UserManagement" ng-controller="UserManagementController">
<h3>to do</h3>
<form ng-submit="addtodo();">
<table>
<tr><td colspan="2"><input type="checkbox" ng-model="employees.todo" /></td></tr>
<tr><td colspan="2">{{remng()}} of {{actuallength}} remaining</td></tr>
<tr ng-repeat="emp in employees">
<td><input type="checkbox" ng-model="emp.todo" /></td>
<td>{{emp.name}}</td>
</tr>
<tr>
<td><input type="text" ng-model="addemp" /></td>
<td><input type="button" value="Add" ng-click="addemps()"/></td>
</tr>
<tr>
<td><input type="button" value="Delete" ng-click="deleteemps();"/></td>
</tr>
</table>
</form>
</body>
here i am making simple add, delete operation of a list of employees. In the delete operation, when i click delete without checking any checkbox, the items with existing checked checkboxes are deleted, but when i click any checkbox and press delete, the clicked checkbox is not deleted this time, but when i click delete second time, it deletes.
Js code:
var app = angular.module("UserManagement", []);
//Controller Part
app.controller("UserManagementController", function($scope, $http) {
$scope.employees = [
{name:'Abhinav',todo:true},
{name:'Amit', todo:false},
{name:'Raghav',todo:true},
{name:'Sumit', todo:false},
{name:'Ashwani',todo:true},
{name:'Mihir', todo:false},
]
$scope.totalsel = $scope.employees.length;
$scope.actuallength = $scope.totalsel;
alert($scope.actuallength);
//$scope.addtodo = function(){}
//alert("ddd");
$scope.deleteemps = function(){
//alert($scope.employees.name);
$scope.deleted_emps = [];
//alert("in foreach: "+$scope.employees[2].todo);
angular.forEach($scope.employees, function(todos, index) {
//alert(todos.todo);
//alert(todos.name);
if(todos.todo){
// alert(index)
var deletednames = todos.name;
// var deletedtodo = todos.todo;
//$scope.deleted_emps.push(deletednames)
// alert(deletednames);
$scope.deleted_emps.push({name:todos.name, todo:todos.todo});
//var abc=angular.toJson($scope.deleted_emps);
// alert(index);
//console.log(angular.toJson(todos.name));
console.log("hiii: "+$scope.deleted_emps.name);
var indx;
for (var i=0; i<$scope.deleted_emps.length; i++) {
console.log("iii: "+$scope.deleted_emps[i].name);
console.log("i: "+$scope.employees[index].name);
//console.log($scope.employees[index].name.indexOf($scope.deleted_emps[i].name));
indx = $scope.employees[index].name.indexOf($scope.deleted_emps[i].name);
// alert(indx);
if (indx > -1) {
// alert(indx);
//$scope.employees.splice()
$scope.employees.splice(index, 1);
}
}
/* var indx;
for (var i=0; i<array2.$scope.deleted_emp; i++) {
indx = array1.indexOf(array2[i]);
if (indx > -1) {
array1.splice(indx, 1);
}
}
*/
}
$scope.actuallength = $scope.totalsel;
})
}
});
I am using angular js 1.6.1 . Thanks in advance.
I've made a fiddle based on your codes.
Add and Delete Employees
Sample code of mine is like this.
$scope.deleteEmp = function(){
var slicedEmps = [];
angular.forEach($scope.employees, function(e){
if(!e.isChecked){
slicedEmps.push(e);
}
});
$scope.employees = slicedEmps;
};
What I suggested is making new array instead of using 'splice'.
I hope this fiddle can help you. :)

Mutliplr print functionality return inconsistent data , on changing $timeout value

I want to print a multiple barcode slip, each will have different barcode.
Using a print service to print the div content,
(function() {
'use strict';
angular.module('app.services')
.factory('PrintService', PrintService);
PrintService.$inject = [];
function PrintService() {
var service = {
printElement: printElement
};
return service;
function printElement(elem) {
var printSection = document.getElementById('printSection');
// if there is no printing section, create one
if (!printSection) {
printSection = document.createElement('div');
printSection.id = 'printSection';
document.body.appendChild(printSection);
}
var elemToPrint = document.getElementById(elem);
// clones the element you want to print
var domClone = elemToPrint.cloneNode(true);
printSection.innerHTML = '';
printSection.appendChild(domClone);
window.print();
window.onafterprint = function() {
printSection.innerHTML = '';
}
};
}
})();
Using this print service, will print the slip. Slip data will bind.
var userServicePromise = UserService.printBarCodes(sampleId);
userServicePromise.then(function(response) {
if (response != null && response.data != null && response.data.result != null) {
response.data.result.forEach(function(entry) {
/* $timeout(function() {
vm.barCodeImage = angular.copy(entry);
}, 0);*/
//vm.testName = item.testMast.testName.slice(0, 3);
vm.barCodeImage = angular.copy(entry);
$timeout(function() {
PrintService.printElement("printThisElement");
}, 1);
});
} else {
toaster.error(response.data.message);
}
});
This is the html which will be printed eventually, using DOM element id for printing.
<div id="printThisElement" class="onlyprint" >
<table>
<tr>
<td>{{ ctrl.instCode }}</td>
<td align="center">{{ ctrl.date | dateDisplayFilter}} </td>
</tr>
<tr>
<td colspan="2" align="center"> <img ng-src="data:image/JPEG;base64,{{ctrl.barCodeImage}}"> </td>
</tr>
<tr>
<td colspan="2" align="center">{{ ctrl.user.name }} </td>
</tr>
<tr>
<td >Reg Id: {{ ctrl.regIdLookup }}</td>
<td align="center">{{ ctrl.testName }}</td>
</tr>
</table>
</div>
Expected out put is three slips with different barcode:
7865
7866
7867
Output is three slips with same barcode
7865
7865
7865
some times,
7866
7866
7866
On changing the $timeout(function() value output be like
7865
7865
7866
what can be the reason for this ?
Never ever modify the DOM from inside a service, that's just totally against the whole way Angular works. What you should do instead is create a model of the data (and it's quite alright to create that in the service) and use Angular's templates to render that model in the page.
The reason your code doesn't work is that you are trying to re-use vm.barCodeImage for different images on the page. Angular tracks the changes and will redraw existing parts of the page. That is why you get the same barcode repeated: the different copies each use the same model so they will be the same.
A simple solution is to create an array ofvm.barCodeImages and then just render them in an ng-repeat loop. A better way might be to create a myBarcode directive which uses UserService.printBarCodes to create one barcode in an isolated scope and then your template will look shorter and tidier.

How can I easily filter on more than one property?

Using Angular v1.5 I've got a simple one property filter working but I would like to filter on two properties. Searching came up with some custom filters but that seemed like a bunch of code to just look at an extra property.
In my below example I would like the filter to work on both FirstName and LastName.
Filter Name: <input type="text" ng-model="memberFilter.FirstName" />
<p />
<div class="table-responsive">
<table class="table table-bordered table-striped table-hover">
<tr class="info">
<th ng-click="doSort('FirstName')">First Name</th>
<th ng-click="doSort('LastName')">Last Name</th>
<th ng-click="doSort('EmailPrimary')">Email</th>
<th ng-click="doSort('PhonePrimary')">Phone</th>
<th> </th>
</tr>
<tr ng-repeat="member in members | filter:memberFilter | orderBy:sortBy:reverse">
<td>{{ member.FirstName }}</td>
<td>{{ member.LastName }}</td>
<td>{{ member.EmailPrimary }}</td>
<td class="text-center">{{ member.PhonePrimary | tel }}</td>
<td class="text-center">View</td>
</tr>
</table>
</div>
I tried adding an array to the ng-model but that didn't work:
ng-model="[memberFilter.FirstName,memberFilter.LastName]"
Updated Question
I'm new with Angular in general and just wrote my first custom filter the other day to display formatted telephone numbers. You can see my filter in the original code but I changed the name from "tel" to "phone". It's one I found on SO and I was able to get it to work. So I assumed I could just add the search filter to this file and not create a new js file for each filter. However, when I added it my Angular stopped working. I thought I added it correct but I might have a semi-colon in the wrong spot or maybe it's not possible. I still haven't figured out a good way to debug in Angular.
Here is a file I created for my filters called filter.js.
angular.module('appFilters', [])
.filter('phone', function () {
return function (phone) {
if (!phone) { return ''; }
var value = phone.toString().trim().replace(/^\+/, '');
if (value.match(/[^0-9]/)) {
return phone;
}
var country, city, number;
switch (value.length) {
case 10: // +1PPP####### -> C (PPP) ###-####
country = 1;
city = value.slice(0, 3);
number = value.slice(3);
break;
case 11: // +CPPP####### -> CCC (PP) ###-####
country = value[0];
city = value.slice(1, 4);
number = value.slice(4);
break;
case 12: // +CCCPP####### -> CCC (PP) ###-####
country = value.slice(0, 3);
city = value.slice(3, 5);
number = value.slice(5);
break;
default:
return phone;
}
if (country == 1) {
country = "";
}
number = number.slice(0, 3) + '-' + number.slice(3);
return (country + " (" + city + ") " + number).trim();
};
})
.filter('customMemberFilter', function () {
return function (memberList, query) {
// make sure a query value was passed
if (query) {
query = query.toLowerCase();
var out = [];
angular.forEach(memberList, function (member) {
if ((member.FirstName.toLowerCase().includes(query)) ||
(member.LastName.toLowerCase().includes(query))) {
out.push(member);
}
});
return out;
} else {
return memberList;
}
}
});
and this is my app.js where the appFilters are added
(function () {
var app = angular.module('troopApp', ['ngRoute','appFilters']); //('moduleName', [array of injected modules])
app.config(function($routeProvider) {
$routeProvider
.when('/', {
controller: 'MembersController',
templateUrl: 'app/views/members.html'
})
.when('/memberDetail/:memberId', {
controller: 'MemberDetailController',
templateUrl: 'app/views/memberDetail.html'
})
.otherwise({ redirectTo: '/'});
});
}());
This is what I changed my HTML code to:
Filter Name: <input type="text" ng-model="memberFilter" />
and
<tr ng-repeat="member in members | customMemberFilter:memberFilter | orderBy:sortBy:reverse">
The solution is very simple.
Change this line:
Filter Name: <input type="text" ng-model="memberFilter.FirstName" />
to this:
Filter Name: <input type="text" ng-model="memberFilter" />
By default Angular will do deep property filtering. Since you were creating an object with a FirstName property to use as your filter you were effectively limiting the filter to that property on your target object(s). By making the filter more generic Angular will attempt to match on any property of the target object(s).
Update: This will, of course, match on all properties of your member object which may be undesirable. If this is the case then, as you suspected, you'll have to write a custom filter. Here's one way you could write it:
.filter('customMemberFilter', function() {
return function(memberList, query) {
// make sure a query value was passed
if (query) {
query = query.toLowerCase();
var out = [];
angular.forEach(memberList, function(member) {
if ((member.FirstName.toLowerCase().includes(query)) ||
(member.LastName.toLowerCase().includes(query))) {
out.push(member);
}
});
return out;
} else {
return memberList;
}
}
})
And then you would use it:
<tr ng-repeat="member in members | customMemberFilter:memberFilter | orderBy:sortBy:reverse">

How to call ng-disabled with a function from web service response

The ng-disabled has a function that takes the response from api and two parameters. But it never gets called after the response.
function PermissionController(permissionResource) {
var vm = this;
vm.message = 'Permission';
vm.permissions;
permissionResource.query(function(data) {
vm.permissions = data;
});
vm.isPermissionMissing = function (r, a) {
for(var i = 0; i < vm.permissions.length; i++) {
if(vm.permissions[i].Resource == r && vm.permissions[i].Action == a)
return -1;
}
return 1;
};
}
module.controller("PermissionController", PermissionController);
Then my view has a button to show/hide with ng-disabled.
<button type="submit" class="btn btn-primary btn-block" ng-disabled="isPermissionMissing('account', 'search')">Search</button>
Then a table with ng-repeat
<table class="table">
<thead>
<tr>
<td>resource</td>
<td>action</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="permission in vm.permissions">
<td>{{ permission.Resource }}</td>
<td>{{ permission.Action }}</td>
</tr>
</tbody>
</table>
Problem is by the time the page loads with the api response, it does not call the function in ng-disabled.
I tried the promise then with no luck.
permissionResource.query(function(data) {
vm.permissions = data;
}).$promise
.then(function (result) {
vm.isPermissionMissing = function (r, a) {
for(var i = 0; i < result.length; i++) {
if(result[i].Resource == r && result[i].Action == a)
return -1;
}
return 1;
};
});
The angular documentation shows ngInit being used with ngDisabled.
https://docs.angularjs.org/api/ng/directive/ngDisabled
In your instance I would move the function call to ng-init. Then in the function you need to create a scope variable to set true/false. Let me know if that works for you.
<button type="submit" class="btn btn-primary btn-block" ng-init="isPermissionMissing('account', 'search')" ng-disabled="{{isDisabled}}">Search</button>
vm.isPermissionMissing = function (r, a) {
for(var i = 0; i < vm.permissions.length; i++) {
if(vm.permissions[i].Resource == r && vm.permissions[i].Action == a)
vm.isDisabled = false;
}
vm.isDisabled = true;
};enter code here

Resources