Let me first explain the issue I am trying to solve.
I have an existing list of Tags(key-value pair), which will be loaded first when a UI dialog will open up. Then user can add more tags, can remove tags or can edit the tags. The API where I will pass the modified tag list, unfortunately, does not support edit. So edit means: delete the modified entry and add the new entry.
An example of the tags are:
const existingTags = [{
"key": "t1",
"value": "v1"
}, {
"key": "t2",
"value": "v2"
}
];
const modifiedTags = [{"key": "t1", "value": "v1"}, {"key": "t2", "value": "v2"}, {"key": "t3", "value": "v3"},];
The code I have tried out is this: (It somehow works, but not elegant). Looking for some element solution, if possible.
<!DOCTYPE html>
<html>
<body>
<h1>JavaScript Arrays</h1>
<h2>The concat() Method</h2>
<p id="demo">TagsToBeAdded</p>
<p id="demo1">TagsToBeRemoved</p>
<p id="demo2">FinalAddList</p>
<script>
const existingTags = [{
"key": "t1",
"value": "v1"
}, {
"key": "t2",
"value": "v2"
}
];
const modifiedTags = [{"key": "t1", "value": "v1"}, {"key": "t2", "value": "v2"}, {"key": "t3", "value": "v3"},];
const tagsToBeAdded = modifiedTags.filter(item1 => !existingTags.some(item2 => (item2.key === item1.key && item2.value === item1.value)));
let tagsToBeDeleted = existingTags.filter(item1 => modifiedTags.some(item2 => (item2.key === item1.key && item2.value !== item1.value)));
const tagsToBeRetained = existingTags.filter(item1 => !tagsToBeDeleted.some(item2 => (item2.key === item1.key && item2.value === item1.value)));
if (!tagsToBeAdded.length && !tagsToBeDeleted.length) {
tagsToBeDeleted = existingTags.filter(item1 => !modifiedTags.some(item2 => (item2.key === item1.key)));
}
const finalTagsListToBeAdded= tagsToBeRetained.concat(tagsToBeAdded);
const children = JSON.stringify(tagsToBeAdded);
const children1 = JSON.stringify(tagsToBeDeleted);
const children2 = JSON.stringify(finalTagsListToBeAdded);
document.getElementById("demo").innerHTML = children
document.getElementById("demo1").innerHTML = children1
document.getElementById("demo2").innerHTML = children2
</script>
</body>
</html>
Some of the examples:
// Input
const existingTags = [{
"key": "t1",
"value": "v1"
}, {
"key": "t2",
"value": "v2"
}
];
const modifiedTags = [{"key": "t1", "value": "v1"}, {"key": "t2", "value": "v21"}, {"key": "t3", "value": "v3"}];
// Expected output:
tagsToBeAdded: [{"key":"t2","value":"v21"},{"key":"t3","value":"v3"}]
tagsToBeDeleted: [{"key":"t2","value":"v2"}]
finalTagsList: [{"key":"t1","value":"v1"},{"key":"t2","value":"v21"},{"key":"t3","value":"v3"}]
// Input:
const existingTags = [{
"key": "t1",
"value": "v1"
}, {
"key": "t2",
"value": "v2"
}
];
const modifiedTags = [{"key": "t1", "value": "v1"}, {"key": "t2", "value": "v2"}, {"key": "t3", "value": "v3"}];
// Expected output:
tagsToBeAdded: [{"key":"t3","value":"v3"}]
tagsToBeDeleted: []
finalTagsList: [{"key":"t1","value":"v1"},{"key":"t2","value":"v2"},{"key":"t3","value":"v3"}]
// Input:
const existingTags = [{
"key": "t1",
"value": "v1"
}, {
"key": "t2",
"value": "v2"
}
];
const modifiedTags = [{"key": "t1", "value": "v1"}]; // t2:v2 is removing
// Expected output:
tagsToBeAdded: []
tagsToBeDeleted: [{"key":"t2","value":"v2"}]
finalTagsList: [{"key":"t1","value":"v1"}]
// Input:
const existingTags = [{
"key": "t1",
"value": "v1"
}, {
"key": "t2",
"value": "v2"
}
];
const modifiedTags = []; // all tags are dropped
// Expected output:
tagsToBeAdded: []
tagsToBeDeleted: [{"key":"t1","value":"v1"},{"key":"t2","value":"v2"}]
finalTagsList: []
Lodash is also ok.
deep-diffthat does exactly what you need. Check it out: npmjs.com/package/deep-diff