Lodash/Javascript Compare array or objects, fail if any props match - javascript

Preferably using Lodash, how can I compare two array of objects, and if any of the properties match, return false, while excluding 'name'.
array1 = [
{
"name": "componentA",
"img": "www.url.com/image1.jpg"
},
{
"name": "componentB",
"header": "this is the default header",
"text": "here is a default text post",
"buttons": [{
"title": "a button",
"url": "http://www.url.com"
}]
},
{
"name": "componentB",
"header": "this is the default header 2",
"text": "here is a default text post 2 ",
"buttons": [
{
"title": "a button 2",
"url": "http://www.url2.com"
},
{
"title": "a second button 2",
"url": "http://www.url2_1.com"
}
]
}
]
vs
array2 = [
{
"name": "componentA",
"img": "www.url.com/imageA.jpg"
},
{
"name": "componentB",
"header": "header changed",
"text": "text post changed",
"buttons": [{
"title": "button changed",
"url": "http://www.website.com"
}]
},
{
"name": "componentB",
"header": "header 2 changed",
"text": "here is a default text post 2 ",
"buttons": [
{
"title": "button 2 changed",
"url": "http://www.website2.com"
},
{
"title": "button 2 changed again",
"url": "http://www.website2_1.com"
}
]
},
]
As you can see every property has changed except in array2[2].text, which would result in error.
The goal is to compare two arrays and be sure none of the default placeholder texts exists in the final array. if any default placeholder texts exists, do not allow a form to submit. Each object has a name key that needs to be excluded from the check as it's what renders the component.
Started by using _.isEqual(), but unsure how go about checking each property between the two.
let results = _.isEqual(array1, array2)

You can use _.isEqualWith and customizer function Loadash Ref
let array1 = [{"name": "componentA","img": "www.url.com/image1.jpg"},{"name": "componentB","header": "this is the default header","text": "here is a default text post","buttons": [{"title": "a button","url": "http://www.url.com"}]},{"name": "componentB","header": "this is the default header 2","text": "here is a default text post 2 ","buttons": [{"title": "a button 2","url": "http://www.url2.com"},{"title": "a second button 2","url": "http://www.url2_1.com"}]}]
let array2 = [{"name": "componentA","img": "www.url.com/imageA.jpg"},{"name": "componentB","header": "header changed","text": "text post changed","buttons": [{"title": "button changed","url": "http://www.website.com"}]},{"name": "componentB","header": "header 2 changed","text": "here is a default text post 2 ","buttons": [{"title": "button 2 changed","url": "http://www.website2.com"},{"title": "button 2 changed again","url": "http://www.website2_1.com"}]},]
let array3 = [{"name": "component3","img": "www.url.com/image1.jpg"},{"name": "componentB","header": "this is the default header","text": "here is a default text post","buttons": [{"title": "a button","url": "http://www.url.com"}]},{"name": "componentB","header": "this is the default header 2","text": "here is a default text post 2 ","buttons": [{"title": "a button 2","url": "http://www.url2.com"},{"title": "a second button 2","url": "http://www.url2_1.com"}]}]
function check(val1,val2,index){
if(index === 'name') return true
}
console.log(_.isEqualWith(array1,array2,check))
console.log(_.isEqualWith(array1,array3,check))
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.15/lodash.min.js"></script>

Related

Disable submit button/loading on the card on submit in JavaScript adaptive cards

I have a form while submitting the card I want submit button to be disable or need a kind of loading for the adaptive card so that can avoid continues submission of form
Could any one please help me
Card:
{
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.3",
"body": [{
"type": "TextBlock",
"text": "Hello !!",
"size": "Medium",
"weight": "Bolder"
},
{
"type": "Container",
"style": "accent",
"items": [{
"type": "TextBlock",
"text": "What was the type?"
},
{
"type": "Input.ChoiceSet",
"id": "call_type",
"style": "compact",
"isRequired": true,
"errorMessage": " required input",
"placeholder": "Please choose",
"choices": [{
"$data": "${Survey.questions[0].items}",
"title": "${choice}",
"value": "${value}"
}]
}
]
}
],
"actions": [{
"type": "Action.Submit",
"title": "Submit"
}]
}
and the card rendering code
var jsonTemplate = "some data",
var jsonDate = "some data"
var template = new ACData.Template(jsonTemplate);
var cardPayload = template.expand({
$root: jsonData
});
var adaptiveCard = new AdaptiveCards.AdaptiveCard();
adaptiveCard.onExecuteAction = function(action) {
alert("Ow!");
}
adaptiveCard.parse(cardPayload);
let renderedCard = adaptiveCard.render();
document.body.appendChild(renderedCard);
Normally the flow is disable submit button(or add loading mask) when the button clicked, then send the submit request to backend.
enable submit button(or remove loading mask) when response comes or the request fails.

How to create a form where one dropdown determines options of another

I need to create a form with 3 dropdown fields, where each dropdown should populate with options based on the selection of the previous one. I have all my data in an object.
For example:
{
"campaign1": {
"name": "Campaign 1",
"projects": {
"job A": [
"proj 1"
],
"job B": [
"proj 2",
"proj 3"
]
}
},
"campaign2": {
"name": "Campaign 2",
"projects": {
"job C": [
"proj 4",
"proj 5",
"proj 6"
],
"job D": [
"proj 7",
"proj 8",
"proj 9"
]
}
}
}
The idea is that first you choose a "Campaign", then the 2nd dropdown shows only the "Jobs" for that campaign, then the 3rd shows only the "Projects" for that job.
I started with https://github.com/json-editor/json-editor but it doesn't seem able to do what I need. I looked at alpaca also, but it's daunting.
Alpaca has an optiontree field type but that doesn't seem to do what I want (in that I'm not assigning 'attributes' to a 'value') although the rendered version behaves the way I want.
I would like to use my data object as is, although I can re-structure it if necessary.
Basically I want something like the driver chooser on nvidia ...
https://www.nvidia.com/download/index.aspx
First pick a type, then a series based on the type, etc...
Thanks!
I just changed the structure of the object for my convenience. It makes the implementation easier. use the index value as value attribute in option tag which can be used in retrieve the child object for next filter. I made a sample code for second filter based on the result of campaign filter.
$('select').on('change', function() {
var selected_index = $(this).children("option:selected").val();
var selected_val = $(this).children("option:selected").html();
var obj = [{
"Campaign 1": {
"name": "Campaign 1",
"jobs": [{
"name" : "job A",
"projects": [
"proj 1"
]},{
"name" : "job B",
"projects": [
"proj 2",
"proj 3"
]}
]}
},{
"Campaign 2": {
"name": "Campaign 2",
"jobs": [{
"name" : "job C",
"projects": [
"proj 4",
"proj 5",
"proj 6"
]},{
"name" : "job D",
"projects": [
"proj 7",
"proj 8",
"proj 9"
]}
]}
}];
jQuery('#select_2').html('');
obj[selected_index[selected_val].jobs.forEach( function(data, index){
jQuery('#select_2').append('<option value="index">data</option>');
});
});
Another option you could use to the replace the data source for each field, depending on the previous selection. Here is a working JS Fiddle where the dropdown options are determined by the previous selection: https://jsfiddle.net/bsunderland/78hybL3v/3/
Also, here is some sample code for setting the options in a select based on a previous field selection, but with a server side call:
"postRender": function(control) {
var parentType = control.childrenByPropertyId["Parent_LookupTypeCode"]; //Grab the Parent Lookup Type Object
var parentCode = control.childrenByPropertyId["Parent_LookupCode"]; //Grab the Parent Lookup Object
parentCode.subscribe(parentType, function(val) {//Subscribe parentCode to changes to parentType
// alert(val);
if(!val) {//val = value of parentType
val="Metrics"; //If missing, do nothing
}
else{
this.options.dataSource = "./ExtraStuff/Load_Lookups.php?q=" + val; //Load values based on val of parentType
}
this.refresh(); //Refresh the form. This is needed. Without it, the updated options won't show
});
}

Searching in array returns only the first result

I'm trying to search in an array and find specific objects based on their category.
But when I run my code, I only get one result. but in the example below, I should have two results because the cat 2 exists in two of the objects!
This is what I have:
var storedArray = [{
"title": "test title 1",
"date_added": "2018-09-26",
"url": "someurl.com",
"filename": "file 1",
"category": "cat 1"
}, {
"title": "test title 2",
"date_added": "2018-10-25",
"url": "someurl.com",
"filename": "file 2",
"category": "cat 2"
},{
"title": "test title 3",
"date_added": "2018-10-25",
"url": "someurl.com",
"filename": "file 3",
"category": "cat 2"
}];
var result = storedArray.find( audio => audio.category === 'cat 2' );
console.log(result);
Could someone please advice on this issue?
Array.prototype.find()
The find() method returns the value of the first element in the array that satisfies the provided testing function. Otherwise undefined is returned.
Array.prototype.filter()
The filter() method creates a new array with all elements that pass the test implemented by the provided function.
From the above, you have to use filter() to get the expected result:
var storedArray = [{
"title": "test title 1",
"date_added": "2018-09-26",
"url": "someurl.com",
"filename": "file 1",
"category": "cat 1"
}, {
"title": "test title 2",
"date_added": "2018-10-25",
"url": "someurl.com",
"filename": "file 2",
"category": "cat 2"
},{
"title": "test title 3",
"date_added": "2018-10-25",
"url": "someurl.com",
"filename": "file 3",
"category": "cat 2"
}];
var result = storedArray.filter( audio => audio.category === 'cat 2' );
console.log(result);
Array.prototype.find() returns the first element found. You are looking for Array.prototype.filter()
You want to use filter function.
From the MDN documentation on find...
The find() method returns the value of the first element in the array that satisfies the provided testing function. Otherwise undefined is returned.
Key word: first.
The method you are using .find() is returning only the first record that matches the condition, this is why you are getting only 1 result.

Check duplicate item in object

I have a structure like this and I want to check if there are duplicate URL in the array so I can target those and make some conditional statements depending on the Keyword property. Thank you in advance.
{
"prochat": [{
"Title": "Multiple KB Page",
"Message": "Hi, Multiple KB Page?",
"ProblemDescription": "Multiple KB Page",
"Keyword": "",
"Template": 1,
"URL": "www.abcd.com"
},
{
"Title": "URL 1",
"Message": "Do you want to Renew?",
"ProblemDescription": "Message about Installing",
"Keyword": "Renewals",
"Template": 1,
"URL": "www.nba.com"
},
{
"Title": "URL 1",
"Message": "Do you want to Install?",
"ProblemDescription": "Message about Installing",
"Keyword": "Installings",
"Template": 1,
"URL": "www.nba.com"
}
]
}
I have a condition statement like this
if (window.location.href.indexOf(data.prochat[i].URL) > -1) { // logic here }
basically I need to match the url and if it matches i''ll show a button. however there are some duplicate url too so I want if there are duplicates I will just rely on Keyword property if it has the same url.
Iterate your data, if the URL is new simply add it to a new array. If it's already in it, handle it as you wish since it is a duplicate.
You can try the following code:
var myJSON = {
"prochat": [{
"Title": "Multiple KB Page",
"Message": "Hi, Multiple KB Page?",
"ProblemDescription": "Multiple KB Page",
"Keyword": "",
"Template": 1,
"URL": "www.abcd.com"
},
{
"Title": "URL 1",
"Message": "Do you want to Renew?",
"ProblemDescription": "Message about Installing",
"Keyword": "Renewals",
"Template": 1,
"URL": "www.nba.com"
},
{
"Title": "URL 1",
"Message": "Do you want to Install?",
"ProblemDescription": "Message about Installing",
"Keyword": "Installings",
"Template": 1,
"URL": "www.nba.com"
}
]
};
var duplicateURLs = [];
for(var key in myJSON.prochat){
if(myJSON.prochat.hasOwnProperty(key)){
if(duplicateURLs.indexOf(myJSON.prochat[key].URL) > 0){
// URL is duplicate, do stuff
}
else{
duplicateURLs.push(myJSON.prochat[key].URL);
}
}
}
You can try it online on jsfiddle.
var newarray=[];
var object={
"prochat": [{
"Title": "Multiple KB Page",
"Message": "Hi, Multiple KB Page?",
"ProblemDescription": "Multiple KB Page",
"Keyword": "",
"Template": 1,
"URL": "www.abcd.com"
},
{
"Title": "URL 1",
"Message": "Do you want to Renew?",
"ProblemDescription": "Message about Installing",
"Keyword": "Renewals",
"Template": 1,
"URL": "www.nba.com"
},
{
"Title": "URL 1",
"Message": "Do you want to Install?",
"ProblemDescription": "Message about Installing",
"Keyword": "Installings",
"Template": 1,
"URL": "www.nba.com"
}
]
}
console.log(object.prochat.length);
for(var i=0;i<object.prochat.length;i++){
for(var j=i+1;j<object.prochat.length;j++){
if(object.prochat[i].URL==object.prochat[j].URL){
console.log("url matches"+i+j);
newarray.push(object.projact[i].URL);
}
}

Unnest a JSon Object returned from api

How can I remove the nested json object returned from an api as shown below and show it as individual fields by unnesting the object using jquery in a generic way. here is my json object
"response": {
"content":
"[ {
"Id": 0,
"Name": "Some name",
"createdOnDate": "0001-01-01T00:00:00",
"keyValueList":
[
{
"Key": "key1",
"Value": "Sample Data key 1"
},
{
"Key": "key2",
"Value": "sample data key 2
] }]"
this is how it should be after unnesting.
[{
"Id": 123,
"Name": "some name",
"createdOnDate": "2013-01-22T17:02:00",
"key1": "this is my key1",
"key2": "this is my key2"
}]
This is invalid JSON. Make sure you're getting valid before.
Afterwards you can iterate through the attributes and set them the way you want.
$.each(content[0]['keyValueList'], function (k, value) {
content[0][value['Key']] = value['Value']
});
delete content[0]['keyValueList'];
http://jsfiddle.net/TjQzv/3/

Categories