I have a JavaScript object with the following properties
{
name:"Request",
data:[1,2,3,4,5,6,7,8,9,10,11,12]
},
{
name:"Waiting",
data:[1,2,3,4,5,6,7,8,9,10,11,12]
}
I have a list that has status (name) and month ( data:[])
First I want to validate whether the object with the name eg "Request" exists.
If it does not exist, create a new object.
{ name:'Request', data:[]}.
If the name already exists, it will check if the month exists in the object array "data". If there is no month in the array you must enter it.
{name:'Request', data:[1]}
I'm not entirely sure what you want to do if everything is successful, but the code below should satisfy the requirements you have provided.
var objs = [{
name:"Request",
data:[1,2,3,4,5,6,7,8,9,10,11,12]
},
{
name:"Waiting",
data:[1,2,3,4,5,6,7,8,9,10,11,12]
}];
var month = 25;
var request = null;
// Validate whether the object with the name eg "Request" exists.
var requestExists = objs.some(function (elem) {
if (elem.name === "Request") {
request = elem;
return true;
}
});
//If it does not exist, create a new object. { name:'Request', data:[]}.
if(!requestExists) {
objs.push({name: "Request", data: []});
}
else {
// If the name does exist, check if the month exists in the "data" array.
// If there is no month in the array you must enter it. {name:'Request', data:[1]}
if (request.data.indexOf(month) === -1) {
request.data.push(month);
}
}
console.log(request);
console.log(objs);
var list = [{
name:"Waiting",
data:[1,2,3,4,5,6,7,8,9,10,11,12]
}]
var request = list.filter(status => status.name == "Request");
if (request.length === 0) list.push({name : "Request", data : [1]});
else if (request[0].data.length === 0) request[0].data.push(1);
console.log(list)
Since with the OP's example a data structure has to be checked and repaired whilst following some rules, a more generic approach should look for kind of a specific sanitizer function that can be both operated by itself (providing the key manually) but also run as a reduce method, if it comes to counterchecking the data structure against more than one data item key (like "Request" as it got provided with the OP's original example).
A solution then most probably will be close to the next provided one.
The Array API Documentation of the Mozilla Developer Network does provide polyfills for Array.isArray and Array.prototype.findIndex
function sanitizeDataList(list, key) {
var
indexOfDataItem = list.findIndex(function (dataItem) {
return (dataItem.name === key);
}),
dataItem = list[indexOfDataItem];
if (!dataItem) {
list.push(dataItem = {
name: key
});
}
if (!Array.isArray(dataItem.data) || (dataItem.data.length <= 0)) {
dataItem.data = [1];
}
return list;
}
var
dataList = [{
name: "Request_A",
data: [1,2,3,4,5,6,7,8,9,10,11,12]
}, {
name: "Waiting_A",
data: [1,2,3,4,5,6,7,8,9,10,11,12]
}/*, {
name: "Request_B",
data: [1,2,3,4,5,6,7,8,9,10,11,12]
}*/, {
name: "Waiting_B",
data: []
}, {
name: "Request_C"
}, {
name: "Waiting_C",
data: [1]
}],
dataItemKeyList = ["Request_A", "Waiting_A", "Request_B", "Waiting_B", "Request_C", "Waiting_C"];
dataList = dataItemKeyList.reduce(sanitizeDataList, dataList);
console.log(dataList);
.as-console-wrapper { max-height: 100%!important; top: 0; }
An easy solution is to use indexOf. You would need for it to be in a variable.
var myarray = [{
name:"Request",
data:[1,2,3,4,5,6,7,8,9,10,11,12]
},
{name:"Waiting",
data:[1,2,3,4,5,6,7,8,9,10,11,12]
}];
var myreturn = false;
for(i = 0; myarray.length > i; i++){
var data = myarray[i];
if(data.name == "Request"){
myreturn = true;
}
if (myreturn === true){
alert('sweet now do some code');
break;
}
}
My initial thought was incorrect, but using a For loop will work.
Related
In my application, there are filters on all list pages.
Now as per requirement, I want to preserve applied filters on browser back button.
E.g say user has applied filters on sales list page.
After that he clicks on one record to go to sales edit page.
Now if user hit browser back button then those applied filters should remain.
To accomplish this i did like below.
On sales list page ,
componentWillMount() {
const { list, checkReportClose,
updateReportCloseStatus } = this.props;
const { inPopState } = this.state;
window.onpopstate = () => {
if (!_.isEmpty(list)) {
this.setState({ filters: JSON.parse(list.input.filters),
inPopState: true}, this.loadList);
}
}
if(!inPopState && inPopState != undefined &&
checkReportClose == false) {
this.loadList();
}
}
Using above code it works fine but while back button it calls the lis page api (this.loadList) twise.
Please suggest some new solution or modification in existing one.
Thanks.
I would suggest using the url to store filters as parameters.
I've written an example below. Let's use http://skylerfenn.com/news?order=asc&category=feature&year=2017 as the url for the functions below.
Step 1: Call getParameters() in the window.onpopstate and store the parameters in state. Using the URL above, getParameters() will return the parameters as the object { order: 'asc', category: 'feature', year: '2017' }.
function getParameters() {
let parameters = window.location.search.replace('?', '');
let currentParameters = {};
if (Object.keys(parameters).length) {
parameters = parameters.split('&');
for (let i = 0; i < parameters.length; i++) {
let parameter = parameters[i].split('=');
currentParameters[parameter[0]] = parameter[1];
}
}
return currentParameters;
}
Step 2: Pass any new parameters to the getNewParameters function below as an object. For example, calling getNewParameters({ order: 'desc', year: null }) returns the object { order: 'desc', category: 'feature' }. Notice that it removes year since it's null.
function getNewParameters(newParameters) {
const parameters = getParameters();
const keys = Object.keys(newParameters);
for (let i = 0; i < keys.length; i++) {
const value = newParameters[keys[i]];
parameters[keys[i]] = value;
if (!value) {
delete parameters[keys[i]];
}
}
return parameters;
}
Step 3: Use the result from getNewParameters to update state. Also pass the result to function below to update your url.
updateUrl(parameters) {
let search = '';
let j = 0;
let separator = '?';
Object.keys(parameters).forEach((key) => {
let value = parameters[key];
if (value) {
if (j !== 0) {
separator = '&';
}
search += `${separator}${key}=${value}`;
j++;
}
});
let newUrl = `${location.origin}${location.pathname}${search}`;
// prevents pushing same url if function won't change url.
if (location.href !== newUrl) {
history.pushState(null, null, newUrl);
}
}
I'm trying to hardcode a kind of log in system, for that i was trying to have two inputs and on click check if those values matched the ones in the array, the array having two objects for two possible answers…
Well, i cant get it to work, all of the suden my variables are not recognized and the overall code has gone kaput… here is the Pen
thanks in advance!
the code so far btw
$(".submit").click(function() {
//bidimensional array
var data = [{
user: "cinco",
pw: "king"
}, {
user: "manco",
pw: "wawa"
}];
var name = $(".name").val();
var pass = $(".pw").val();
if (data.user.includes(name) && data.pw.includes(pass)) {
$(".check-input").addClass('valid');
} else {
$(".check-input").addClass('invalid');
}
});
$(".input").focus(function() {
$(".check-input").removeClass("valid");
$(".check-input").removeClass("invalid");
});
You can use find() like this
if (data.find(v => v.user === name && v.pw === pass)) { ... }
Please note that using javascript as your login is highly insecure as everybody can just open the console and read the credentials.
For your comment, the => is part of an arrow function, it boils down to
if (data.find(function(v) {
return v.user === name && v.pw === pass;
})) { ... }
var data = [{
user: "cinco",
pw: "king"
}, {
user: "manco",
pw: "wawa"
}];
checkLogin(usr, pwd){
for(var index in data) {
var obj = data[index];
if(obj.user == usr && obj.pw == pwd) {
return true;
}
}
return false;
}
checkLogin('chino', 'wrongPwd'); // returns false
checkLogin('chino', 'king'); // returns true
You need to access the individual objects in the array and get the user and pw properties of those objects. The array itself doesn't have those properties.
Here's a working version that also streamlines your code:
$(".submit").click(function() {
// This is not a bidimensional array. It's just an array of objects
var data = [{
user: "cinco",
pw: "king"
}, {
user: "manco",
pw: "wawa"
}];
var name = $(".name").val();
var pass = $(".pw").val();
// You need to access the individual objects in the array and get
// the user and pw properties of those objects. The array itself
// doesn't have those properties.
// Loop through the array and check each object
// You can't return from a forEach loop, so we'll set up a variable
// that will be used after the loop is complete
var valid = false;
data.forEach(function(obj){
// Don't check for inclusion of the data, check for exact match
if (obj.user === name && obj.pw === pass) {
valid = true;
}
});
// Now that the loop is done, set the validity
$(".check-input").addClass(valid ? 'valid' : 'invalid');
});
$(".input").focus(function() {
$(".check-input").removeClass("valid");
$(".check-input").removeClass("invalid");
});
.check-input{
width:250px;
height:40px;
background-color:gray;
}
.valid{
background-color:green;
}
.invalid{
background-color:crimson;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" class="input name">
<input type="text" class="input pw">
<button class="submit">Submit</button>
<div class="check-input"></div>
Im trying to compute if an array has a particular object that has a value which matches to what I want
The array is membersArray and here is where it comes from
<firebase-query
id="querymembers"
path="/members"
order-by-child="crew"
equal-to="[[routeData.key]]"
data="{{membersArray}}">
</firebase-query>
The property
_isUserAMember: {
type: Boolean,
computed: '_computeIfIsMember(membersArray,user)'
},
And the function itself
_computeIfIsMember: function(membersArray, user) {
if(user && membersArray) {
// var found = false;
// for(var i = 0; i < membersArray.length; i++) {
// if (membersArray[i].userid === user.uid) {
// found = true;
// break;
// }
// }
// return console.log(found);
return console.log(membersArray.some(function(el) {
return el.crew === username;
}));
}
},
I keep getting false. What could I be doing wrong ?
This is how the members path looks like
console.log(typeof(this.membersArray)); // object
Assuming that firebase query will only return a result if the user.uid equal-to the child, I don't think you need to recheck the result.
I have pretty complex query that I am trying to write and can't seem to wrap my head around the best way to write it. Ultimately I am trying to avoid having to write it all out manually. What I am trying to do is to take a dynamic field and go through each document to see if that field exists and if it does then update it. The issue is that the field can exist more than once in document since it can exist on an embedded level in multiple embedded documents per single parent document.
Here is what a typical object would look like:
applications: {
_id: 5368hss76sd9f,
ProgramAreaId: 1,
ProgramArea: 'Education',
StrategyId: 16,
Strategy: 'Graduate Program',
AlternateMapping: [{
ProgramAreaId: 2,
ProgramArea: 'Private Sector',
StrategyId: 13,
Strategy: 'Higher Education Fund'
}],
Funding: [{
Amount: '500000'
StrategyId: 16
Strategy: 'Graduate Program'
},
{
Amount: '500000'
StrategyId: 13
Strategy: 'Higher Education Fund'
}
]
}
I may have several thousand of these that I will need to update at a time. The ultimate goal would be to do it in one query. I have made it work for a single field at the base level but was wondering if there was a way to make it work for all of the fields that match the dynamic name even in embedded documents.
Here is what I have tried so far:
var fieldId = obj.Type + 'Id'; //obj.Type could equal 'Strategy' or 'ProgramArea'
var field = obj.Type;
var id = 13; //This could be any number of ids and ultimately was what I want to match on.
var qry = {
$where: function() {
var deepIterate = function(o, value) {
for (var field in o) {
if (field == fieldId && obj[field] == value) {
console.log()
return true;
}
var found = false;
if (typeof o[field] === 'object') {
found = deepIterate(o[field], value)
if (found) {
return true;
}
}
}
return false;
};
return deepIterate(this, id)
}
};
var setQry = { $set: {} };
setQry.$set[field] = obj.Name;//Field here would be 'Strategy' or 'ProgramArea' or any number of other fields I could be updateing and Name is what I want the value of that field to equal.
mongo.collection('applications').updateMany(qry, setQry, function(err, result) {
if (err)
callback(null);
else
callback(result);
});
The above query will find me any 'application' that contains the field name equal to the field name I am asking for and it will even search through embedded documents to see if that field is there. The issue with the above query is that it will only update that field on the parent level rather than updating the children as well.
So I think I have found the best solution to the above code. I created this following code to accomplish the above issue and it works wonderfully!
var resultsArray = [];
var fieldId = obj.Type + 'Id';
var field = obj.Type;
if (coll == 'statuses') {
fieldId = "StatusId";
field = "Status";
}
var altmapField = 'AltMaps.' + fieldId,
altfundField = 'AltFunds.' + fieldId,
paymentField = 'Payments.' + fieldId,
reportField = 'Reports.' + fieldId,
crosswalkField = 'Crosswalk.' + fieldId,
regionField = 'RegionBreakdowns.' + fieldId,
sectorField = 'SectorBreakdowns.' + fieldId;
var qry = [];
qry.push({
$match: {
$or: [{
}, {
}, {
}, {
}, {
}, {
}, {
}, {
}]
}
});
qry[0].$match.$or[0][fieldId] = id;
qry[0].$match.$or[1][altmapField] = id;
qry[0].$match.$or[2][altfundField] = id;
qry[0].$match.$or[3][paymentField] = id;
qry[0].$match.$or[4][reportField] = id;
qry[0].$match.$or[5][crosswalkField] = id;
qry[0].$match.$or[6][regionField] = id;
qry[0].$match.$or[7][sectorField] = id;
var cursor = mongo.collection(collectionPrefix + 'applications').aggregate(qry, { allowDiskUse: true, explain: false }, null);
Essentially all I did was build out a query dynamically and then pass that into mongo aggregation and it read it like a champ.
I do not know how can i delete element in localStorage loop
In save method i add element and check for it duplicate
explain please how can i delete element using for example only id or all values
My Factory
.factory('SaveDocuments', function() {
var documents = [];
save: function (id, name, link) {
if(documents.filter(function(a){return a.id==id}).length)
{ alert('conflict!'); }
else {
// add to it,
documents.push({id: id, name: name, link: link});
// then put it back.
localStorage.setItem('document', JSON.stringify(documents));
}
},
del: function(id, name, link) {
if(documents.filter(function(a){return a.id==id}).length) {
for (i = 0; i < localStorage.length; i++){
key = localStorage.key(i);
value = localStorage.getItem(key);
localStorage.removeItem(value);
console.log(value);
break;
}
}
else {
alert('conflict!');
}
}
}
MyController
.controller('PageSearchCtrl', function($scope, ConstSearch, SaveDocuments) {
$scope.saveDocument = function() {
//Create new project
$scope.document = [{"id": 1, "name": "new1", "link": "#/const"}];
SaveDocuments.save($scope.document[0].id,$scope.document[0].name,$scope.document[0].link);
};
$scope.deleteDocument = function () {
$scope.document = [{"id": 1, "name": "new1", "link": "#/const"}];
//Create new project
SaveDocuments.del($scope.document[0].id,$scope.document[0].name,$scope.document[0].link);
}
I recommend changing your service to something like the following:
.factory('SaveDocuments', function () {
var lsKey = 'document', // the key to store the docs in local storage under
documents = JSON.parse(localStorage.getItem(lsKey) || '[]'); // initialise from localStorage
function saveToLocalStorage() {
localStorage.setItem(lsKey, JSON.stringify(documents));
}
return {
save: function (id, name, link) {
if (documents.filter(function (a) {
return a.id == id;
}).length) {
alert('conflict!');
} else {
// add to it,
documents.push({
id: id,
name: name,
link: link
});
saveToLocalStorage();
}
},
del: function (id, name, link) {
// clear all if del() is called with no arguments or null for all args
if (!id && !name && !link) {
documents = [];
saveToLocalStorage();
return;
}
var initialLength = documents.length;
documents = documents.filter(function (doc) {
return (!id || doc.id !== id) && (!name || doc.name !== name) && (!link || doc.link !== link);
});
// if nothing was removed, show error
if (documents.length === initialLength) {
alert('conflict!');
} else {
saveToLocalStorage();
}
}
};
});
Note that I correctly initialised it from the local storage state when the application starts (so when you reload the page the data is there correctly), used a variable to hold the only key you use to store the data in local storage (to keep the code DRY), and fixed your del() method so it keeps ones which don't match the deletion criteria or deletes everything if no arguments passed in, then just overwrites the value in local storage with the updated state.
NB: You should test this, I did not do any testing to see if this works.