I am very new to AngularJS and currently I am working on a form which is designed in angularjs.
My task is to validate a textbox input with a list. If the value entered in textbox is not present in the list then it should throw a validation error.
I have written the below lines of code for getting the list items through rest API:
app.factory("EatonScanningFactory", ['$http', function($http) {
var EatonScanningFactoryObj = {};
EatonScanningFactoryObj.GetToolMaxTimeList = function (columnName) {
return $http({
method: 'GET',
url: _spPageContextInfo.webAbsoluteUrl
+ "/_api/web/lists/getbytitle('Tool%20Max%20Time')/Items/"
+ "?$select=Text,Value&$orderby=Text&$filter=Title eq '" + columnName + "'",
headers: { "Accept": "application/json;odata=verbose" }
});
}
It will return the list items into an array.
The below lines of code are for accessing calling the above function:
var getToolId = EatonScanningFactory.GetToolMaxTimeList('ToolNumber');
var getMaxLife = EatonScanningFactory.GetToolMaxTimeList('MaxLife');
I am unable to proceed further as I am not sure how to validate if my text box input is available in the list or not.
Please help
Hi there here is a plausible solution as an example:
$scope.list = EatonScanningFactory.GetToolMaxTimeList('MaxLife');
Javascript (Native) Example:
function validateList() {
var IsInList = false;
for (var i = 0; i < $scope.list.length; i++) {
if ($("#textbox").val() == $scope.list[i].listvalue) {
IsInList = true;
break;
}
}
return IsInList;
}
Angular Example:
$scope.validateFunction = function() {
angular.forEach($scope.list, function(value, key){
var IsInList = false;
if($("#textbox").val() == value.listvalue) {
IsInList = true;
break;
}
});
return IsInList;
}
//Invoke the function like follow:
$scope.validateFunction();
Related
Using Angularjs here:
I have a form where user fills up some data and clicks save button to save data :
$scope.save = function (isValid) {
if (isValid) {
if (!$scope.checkBoxChecked) {
$scope.getExistingName($scope.uName);
}
var name = $scope.uName != '' ? $scope.uName? : 'testuser';
//Call save api
}
else {
return false;
}
};
In the save method I am checking for uname, which gets it value by calling another api as below:
$scope.getExistingName = function (uName) {
myService.getDataFromApi(uName).then(function (data) {
var existingSetName = '';
if(data.length >0)
{
$scope.uName = data[i].uName;
}
});
}
The issue is $scope.uName in my Save button is always ''. I tried to debug and found out that the result from the $scope.getExistingName method
being is promise is deffered and returned after the orignal call. Because of which my $scope.uName is empty.
What am I missing here?
--Updated---
Save method:
var name = $scope.getExistingName($scope.uName);
Updated getExistingName
$scope.getExistingName = function (uName) {
return myService.getDataFromApi(uName).then(function (data) {
var existingSetName = '';
if(data.length >0)
{
return data[i].uName;
}
});
}
--This works--
if (!$scope.checkBoxChecked) {
$scope.getExistingName($scope.uName).then(function(data)
{
var name = $scope.uName != '' ? $scope.uName? : 'testuser';
//Call save api
});
}
else
{
var name = $scope.uName != '' ? $scope.uName? : 'testuser';
//Call save api
}
I'm looking for a AngularJS-based way to prevent multiple submits per task.
I don't need buttons to be disabled after submission or close the form and wait for the task to be completed. Instead, I need requests to be unique.
To be more detailed, I need $http.get and $http.post stop sending multiple same requests.
Any Ideas?
According to this article, you can use provider decorator.
NOTE: this approach is based on angular-api
https://gist.github.com/adambuczynski/354364e2a58786e2be71
UPDATE
I've changed a little part in your suggested solution, because returned promises have lost .success and .error and .then.
Just use this edited code to have all of those functions working:
.config(["$provide", function ($provide) {
$provide.decorator('$http', function ($delegate, $q) {
var pendingRequests = {};
var $http = $delegate;
function hash(str) {
var h = 0;
var strlen = str.length;
if (strlen === 0) {
return h;
}
for (var i = 0, n; i < strlen; ++i) {
n = str.charCodeAt(i);
h = ((h << 5) - h) + n;
h = h & h;
}
return h >>> 0;
}
function getRequestIdentifier(config) {
var str = config.method + config.url;
if (config.data && typeof config.data === 'object') {
str += angular.toJson(config.data);
}
return hash(str);
}
var $duplicateRequestsFilter = function (config) {
if (config.ignoreDuplicateRequest) {
return $http(config);
}
var identifier = getRequestIdentifier(config);
if (pendingRequests[identifier]) {
if (config.rejectDuplicateRequest) {
return $q.reject({
data: '',
headers: {},
status: config.rejectDuplicateStatusCode || 400,
config: config
});
}
return pendingRequests[identifier];
}
pendingRequests[identifier] = $http(config);
$http(config).finally(function () {
delete pendingRequests[identifier];
});
return pendingRequests[identifier];
};
Object.keys($http).filter(function (key) {
return (typeof $http[key] === 'function');
}).forEach(function (key) {
$duplicateRequestsFilter[key] = $http[key];
});
return $duplicateRequestsFilter;
})
}])
It could be a performance issue but following idea could solve your problem.
Store the each request URL and DATA as key value pair on a variable. URL should be KEY. For Same URL multiple submission can be stored in a Array.
Then for any new call check the URL if it present in your stored object, then compare the data with each object thorughly (deep check, it is costly though).
If any exact match found then stop the processing. As same request came.
Other wise proceed and don't forget to store this data also.
But it is costly since need to check the data which could be havy.
Note: At the time of storing the data you could convert it to JSON String so it will be easier to compare between String.
here is the Code Algo
YourService.call(url, params) {
var Str1 = JSON.stringify(params);
if(StoredObj[url]) {
for each (StoredObj[url] as Str){
if(Str === Str1) {
return;
}
}
}
else {
StoredObj[url] = []; //new Array
}
StoredObj[url].push(Str1);
Call $http then;
}
have a some data one my page that is in a ng-repeat.
When the page and data 1st loads the data shows up.
When I move away from the page (using Angular Routing) make a change to the data (gets saved in db) then come back into the page (make call to db get new data) the ng-repeat data does not refresh. I can see the new data loading into the array and it is the new data.
I start the process on the page with
var sp = this;
sp.viewData = [];
sp.employee = [];
sp.ViewDataTwo = [];
$(document).ready(function () {
var testHeader = setInterval(function () { myTimer() }, 1000);
function myTimer() {
if (addHeaderToken() != undefined) {
clearInterval(testHeader);
sp.usageText = "";
if (sessionStorage.getItem(tokenKey) != null) {
sp.associatedInfo = JSON.parse(getassociatedInfo());
loadDataOne();
loadDataTwo();
}
}
}
});
I do this because I need to get my security toke from a JS script that I have no power over changes. So I need to make sure the code has ran to get me the token.
here are the functions I call..
function loadPasses() {
$http.defaults.headers.common.Authorization = "Bearer " + addHeaderToken();
$http.get('/api/Employee/xxx', { params: { employeeId: sp.employeeId } }).then(function (data) {
sp.viewData = data.data;
for (var i = 0; i < $scope. viewData.length; i++) {
sp.passes[i].sortDateDisplay = (data.data.status == "Active" ? data.data.DateStart + "-" + data.data[i].DateEnd : data.data[i].visitDate);
sp.passes[i].sortDate = (data.data[i].status == "Active" ? data.data[i].DateStart: data.data[i].visitDate);
}
});
}
function loadDataTwo () {
$http.defaults.headers.common.Authorization = "Bearer " + addHeaderToken();
if (sessionStorage.getItem(tokenKey) != null) $http.get('/api/Employee',
{
params: { employeeId: sp.employeeId }
}).then(function (data) {
sp.employee = data.data;
var tempPassString = "";
sp.ViewDataTwo = [];
var totalA = 0;
var totalU = 0;
for (var p = 0; p < sp.employee.dataX.length; p++) {
sp.ViewDataTwo.push(sp.employee.dataX[p].description + "(" + /** math to update description **// + ")");
totalA += parseInt(parseInt(sp.employee.dataX[p].Anumber));
totalU += parseInt(sp.employee.dataX[p].Bnumber));
}
sp.usageArr.push(" Total: " + totalA- totalU) + "/" + totalA + " Available");
//$scope.$apply();
});
}
One my view sp.viewData and sp.ViewDataTwo are both in ng-repeats.
Works well on load.. when I go out and come back in. I see the data reloading. But the view does not.
I have hacked the Dom to get it to work for now. But I would like to do it the right way..
Any help.
I have used
$scope.$apply();
But it tells me the digest is already in process;
the views are in a template..
Please help
I have create a filter but this filter is not working with array inside array.
'http://plnkr.co/edit/oygy79j3xyoGJmiPHm4g?p=info'
Above plkr link is working demo.
app.filter('checkboxFilter', function($parse) {
var cache = { //create an cache in the closure
result: [],
checkboxData: {}
};
function prepareGroups(checkboxData) {
var groupedSelections = {};
Object.keys(checkboxData).forEach(function(prop) {
//console.log(prop);
if (!checkboxData[prop]) {
return;
} //no need to create a function
var ar = prop.split('=');
//console.log("ar is - "+ar);
if (ar[1] === 'true') {
ar[1] = true;
} //catch booleans
if (ar[1] === 'false') {
ar[1] = false;
} //catch booleans
/* replacing 0 with true for show all offers */
if(ar[0]=='SplOfferAvailable.text'){
ar[1]='true';
}else{
}
//make sure the selection is there!
groupedSelections[ar[0]] = groupedSelections[ar[0]] || [];
//at the value to the group.
groupedSelections[ar[0]].push(ar[1]);
});
return groupedSelections;
}
function prepareChecks(checkboxData) {
var groupedSelections = prepareGroups(checkboxData);
var checks = [];
//console.log(groupedSelections);
Object.keys(groupedSelections).forEach(function(group) {
//console.log("groupedSelections- "+groupedSelections);
//console.log("group- "+group);
var needToInclude = function(item) {
//console.log("item- "+item);
// use the angular parser to get the data for the comparson out.
var itemValue = $parse(group)(item);
var valueArr = groupedSelections[group];
//console.log("valueArr- "+valueArr);
function checkValue(value) { //helper function
return value == itemValue;
}
//check if one of the values is included.
return valueArr.some(checkValue);
};
checks.push(needToInclude); //store the function for later use
});
return checks;
}
return function(input, checkboxData, purgeCache) {
if (!purgeCache) { //can I return a previous 'run'?
// is the request the same as before, and is there an result already?
if (angular.equals(checkboxData, cache.checkboxData) && cache.result.length) {
return cache.result; //Done!
}
}
cache.checkboxData = angular.copy(checkboxData);
var result = []; // this holds the results
//prepare the checking functions just once.
var checks = prepareChecks(checkboxData);
input.every(function(item) {
if (checks.every(function(check) {
return check(item);
})) {
result.push(item);
}
return result.length < 10000000; //max out at 100 results!
});
cache.result = result; //store in chache
return result;
};
});
above code is for check box filter.
when i click on checkbox called "Availability" it does not filter the result.
Please help me out.
Thanks.
I think that the way you are navigating through json is wrong because if you put in this way it works
"Location": "Riyadh",
"AvlStatus": "AVAILABLE"
"Rooms": {.....
You have to go in some way through Rooms and right now I think you're not doing that
I had in my old project this bit of code for an API:
.factory('Api', ['$resource', 'apiUrl', function ($resource, api) {
var Api = $resource(api + ':path', {
path: '#path'
});
return Api;
}])
and then I had an Order model which extended this factory class like this:
.factory('Order', ['$filter', 'Api', function ($filter, api) {
var Order = api;
angular.extend(Order.prototype, {
getDescription: function () {
var rolls = 0,
cuts = 0,
skus = [],
lines = $filter('orderBy')(this.lines, 'sku');
for (var i = 0; i < lines.length; i++) {
var line = lines[i];
switch (line.type) {
case 0: // cut
cuts++;
break;
case 1: // roll
rolls++
break;
}
if (skus.indexOf(line.sku) == -1) {
skus.push(line.sku);
}
}
var description = '';
description += cuts > 0 ? cuts > 1 ? cuts + ' x cuts' : cuts + ' x cut' : '';
description += rolls > 0 && description.length > 0 ? ', ' : '';
description += rolls > 0 ? rolls > 1 ? rolls + ' x rolls' : rolls + ' x roll' : '';
description += skus.length == 1 ? ' of ' + skus[0] : '';
return description;
},
getStatus: function () {
var lines = this.lines,
status = lines[0].status;
for (var i = 0; i < lines.length; i++) {
var line = lines[i];
if (status !== line.status)
return 'Multiple';
}
return status;
},
getDeliveryDate: function () {
var lines = this.lines,
date = lines[0].dates.delivery;
for (var i = 0; i < lines.length; i++) {
var line = lines[i];
if (date !== line.dates.delivery)
return 'Multiple';
}
date = new Date(date);
return date;
},
getDispatchDate: function () {
var lines = this.lines,
date = lines[0].orderDate;
for (var i = 0; i < lines.length; i++) {
var line = lines[i];
if (date !== lines.orderDate)
return 'Multiple';
}
date = new Date(date);
return date;
}
});
return Order;
}]);
Now, I have recently changed my API factory to this:
// ---
// CONSTANTS.
// ---
.constant('apiUrl', 'http://localhost:54326/')
//.constant('apiUrl', 'http://localhost:81/')
// ---
// SERVICES.
// ---
.service('Api', ['$http', 'HttpHandler', 'apiUrl', function ($http, handler, apiUrl) {
// Private function to build our request
var buildRequest = function (url, method, data, params) {
var model = {
method: method,
url: apiUrl + url,
data: data,
params: params
};
return $http(model);
}
// GET
this.get = function (url, params) {
return handler.loadData(buildRequest(url, 'GET', null, params));
}
// POST
this.post = function (url, data) {
return handler.loadData(buildRequest(url, 'POST', data));
}
// PUT
this.put = function (url, data) {
return handler.loadData(buildRequest(url, 'PUT', data));
}
// DELETE
this.delete = function (url, data) {
return handler.loadData(buildRequest(url, 'DELETE', data));
}
}])
When I did this, my order model no longer works. I get an error stating:
Cannot read property '$$hashKey' of undefined
Is there a way I can get my Order model to use the new API factory? Specifically I want to attach functions each object returned by the API.