Dynamic table in Angular send only changed data to API - node.js

I'm trying to achieve the functionality of dynamic table in Angular where data comes from backend first(Express) and then fills the data. I can also add new row to table and send data through it.
I'm able to successfully do it by sending all the data of table to API using formdata. Now I want is only the data which I've changed will be send to API and not the whole data.
This is my table:
On ngOnInit(), I'm calling API and saving data like this.collections = res.data
On Add Row, new row gets added with code:
addImage() {
const obj: Collection = {
uid: '',
image: '',
description: '',
price: ''
}
this.collections.push(obj)
}
On changing the text in input field, I'm using (input) property and passing the data to onInputChange()
onInputChange(text: string, i: string, property: string) {
this.collections[i][property] = text
}
Now my this.collections will have all the data which I'm send via POST API call on Save button i.e., all 3 rows here.
If I don't make any changes still this.collections will send that data. What I want is only changed data is send (like I changed only 1 row so only that data is send)
I tried achieving it by creating a new empty collecctionToAdd object and add data to it on onInputChange() like this, but since it is on (input) event, it keeps on changing for each text field.
if(this.collections[i][property] !== text) {
this.collectionToAdd[i][property] = text
}
Any idea or suggestions on how to achieve this?
Thanks in advance!

You can keep your "collecctionToAdd" logic.
I guess that you have a ngFor of "this.collections". So you need to do something like *ngFor="let item of collections; let i = index" in order to get the index of the element in the original collection an then:
initialize collecctionToAdd as empty Object:
private collecctionToAdd = {};
Make a function like this:
rowChange(text: string; field: string, index: number){
if(!this.collecctionToAdd[index]){
// use spread operator in order to keep the original object untouched or not. Remove it if u want
this.collecctionToAdd[index] = {...this.collecction[index]};
}
this.collecctionToAdd[index][field] = text;
}
and in your submit function:
submit(){
const rowsToSubmit = []
for (const key in this.collecctionToAdd) {
const element: any = this.collecctionToAdd[key];
rowsToSubmit.push(element);
}
}
NOTE: In the example i used "array syntax" in order to use variables for access and create propeties on object.

Related

How to fill a reference field automatically in Wix (Velo), with or without code?

I am using a reference field, which contains users nickname, to make a connection between my main collection and 'public data' collection created as default by Wix. I created this reference field to populate a repeater from the two 'main' and 'public data' collections. Is it possible to automatically fill a reference field without using code? If not, then how can use 'beforeInsert' hook to fill the 'the reference' field using code.
I tried to do so in the backend by this code, but it doesn't work.
import { currentMember } from 'wix-members-backend';
export function Collection1_beforeInsert(item, context) {
currentMember.getMember()
.then((member) => {
const id = member._id;
const fullName = `${member.contactDetails.firstName} ${member.contactDetails.lastName}`;
const nickname = member.profile.nickname
console.log(nickname)
item.referenceField= "nickname"
// return member;
})
.catch((error) => {
console.error(error);
});
return item;
}
First off, I'm assuming you're using a regular reference field and not a multi reference field.
Second, it's important to understand how reference fields work before continuing. The reference field holds the ID of the item it is referencing. So when you say the reference field contains a user's nickname, that can't be true. It can contain the ID of the item in PrivateMembersData collection with the nickname you want.
Third, as just mentioned, the nickname field does not exist in the PublicData collection. It is part of the PrivateMembersData collection.
So, if you want to connect your collection to another with the nickname field, you need to set your reference field to reference the PrivateMembersData collection and then store the proper ID in that field.
(Side point: In your code you are putting the same string, "nickname", in every reference field value. You probably meant to use nickname without the quotes. You're also not using promises correctly.)
You can try this code. It should get you closer to what you're looking for.
import { currentMember } from 'wix-members-backend';
export async function Collection1_beforeInsert(item, context) {
const member = await currentMember.getMember();
item.referenceField = member._id;
return item;
}

How to handle POSTing a multiple select with nothing selected and clearing the field in the mongodb document?

Using Node + Mongoose, I've got something that works, but I wonder if I'm missing an easier way to do this.
I have a mongoose schema called ClipsConfiguration with the following:
exclude_words: {
type: [String],
default: undefined,
set: function (v) {
return typeof v === "object"
? v.filter((elm) => elm !== "")
: undefined;
},
},
I have a page (jade template) that allows you to edit this field using an html multiple select (named "excluded_phrases") using Bootstrap5 tags, see https://github.com/lekoala/bootstrap5-tags
input(hidden, value="", name="exclude_words")
select.form-select#exclude_words(name="exclude_words", multiple, data-allow-new="true", data-allow-clear="true", data-placeholder="type words or phrases and hit enter")
if config.exclude_words
each phrase in config.exclude_words
option(value="#{phrase}", selected) #{phrase}
The hidden input ensures that exclude_words always exists in the form data, even if there are no selected options in the select.
Then in my POST method, I currently do this in code when creating a new config doc or finding an existing config doc, then saving.
config = await Configuration.findOne({
user_id: req.user._id,
});
if (!config) {
config = new ClipsConfiguration(req.body);
config.user_id = req.user._id;
config.token = uuidv4();
} else {
config.set(req.body);
}
config.save();
The outcome is that if the select element has no options, the form data still contains an empty string. The set method on the mongoose schema checks to see if the submitted data is an array. If it is, it filters out the empty string from the submitted contents. If it's only the empty string from the hidden input, it saves the value as undefined, thus removing the field from the mongo document.
This behaves as I need it to, but my question is, have I created something more complicated than necessary?

SuiteScript Updating Search Result Fields

I have a search in SuiteScript 2.0 that's working fine. But for each record the search brings back, I want to update a particular field (I use it elsewhere to determine that the record has been examined). It's potentially a very large result set, so I have to page it. Here's my code:
var sResult = mySearch.runPaged({pageSize: 10});
for (var pageIndex = 0; pageIndex < sResult.pageRanges.length; pageIndex++)
{
var searchPage = sResult.fetch({ index: pageRange.index });
searchPage.data.forEach(function (result)
{
var name = result.getValue({ name: "altname"})
result.setValue({
name: 'tracker',
value: new Date()
})
});
}
You can see where I have a call to result.setValue(), which is a non-existent function. But it shows where I want to update the 'tracker' field and what data I want to use.
Am I barking up the wrong tree entirely here? How do I update the field for each result returned?
As Simon says you can't directly update a search result, but you can use submitFields method.
This example is from NetSuite documentation:
var otherId = record.submitFields({
type: 'customrecord_book', //record Type
id: '4', // record Id
values: {
'custrecord_rating': '2'
}
});
This approach will save more governance than load and save the record.
AFAIK You can't directly update a search result and write the value back to the record, the record needs to be loaded first. The snippet doesn't say what the type of record it is you're searching for or want to load, but the general idea is (in place of your result.setValue line):
var loadedRecord = Record.load({type:'myrecordtype', id:result.id});
loadedRecord.setValue( {fieldId:'tracker', value: new Date() });
loadedRecord.save();
Keep in mind SuiteScript governance and the number of records your modifying. Load & Save too many and your script will terminate earlier than you expect.
Bad design: instead of using result.setValue inside the iteration, push those to an "update" array then after the data.forEach have another function that loops thru the update array and processes them there with record.submitFields()
Be careful of governance....

how can i store objects in a global array or any data Structure so that i can use that array like a database in my program

what i exactly want is to store some Data Locally in a Array of Objects in my Program so that i can use that Data all day long and by the End of the Day i want to delete it without the use of Databases. I have a Json data and i want to Store them as object with a universally unique identifier (uuid) in an Array or data Structure so that i can use it in my Program, i cant use a Database, i think i must find a way to store the Objects in a global Array but i want to append new Objects to that Array without deleting the Objects that are already stored in that Array. I'm using Node js, I'm pretty sure there is a way to do this but i dont know how. I ll apreciate some Help
I tried to Declare classes with Array Property and Store my Data in that Array but when i reexecute the code, the data is deleted and i lost my Data, but i must find a way like a Local Storage in a global Array where my Data will be safe if I append some Objects to that Array and I'm Ok if that Data will be deleted at the End of the Day if I turn off my Laptop for example or if I end the Program and close Vs Code. I tried also to declare it in extra files and call it from the main program but nothing worked
// this is a library to create a universilly unique id
const uuid = require("uuid/v1");
var todo_list = {
todos: [],
register : function(todo) {
this.todos.push({
id : uuid(),
todo: todo
})},
size : function() {return this.todos.length },
display : function() {
this.todos.forEach(t=> {
console.log(t);
});
}
}
function createtodo(id, name, region) {
return {
id : id,
name : name,
region : region
};
}
todo_list.register(createtodo(2,"test6", "leipzig"));
console.log(todo_list.size());
console.log(todo_list.display());
i expect that when a register a new todo that it ll be appended in the todos Array Property and not replace what actually inside the todos in the moment.
If i call the function register 5 times then 5 objects will be stored in my todos Array but if I Comment the code of register function calling and execute the Program another time, then my data will be lost and the result of the size function will be 0 or undifined. the result that i want is that my data will be stored in an extra global Array where the data will not be lost even after i change the code but i understand that the data will be lost if i close the program somehow

Replace key-value pair in an object with Google Apps Script

I am making a call to an API for a commercial product using Apps Script. Unfortunately, the resulting object has several key-value pairs that contain the id from a linked table.
I can easily get the standard values and have written code to find the related name value and add it to the object. I would prefer to add the name in the same location as the original id. But, when I add a new key, it is added to the end of the object.
I want the name in the same location as id so when I insert it into a sheet, the columns will still be in order.
This is my object:
var json = {id: 4730183,name: "A A", customer_source_id:123, company: "NE Company"};
This is my desired object after replacing the id with the name:
var json = {id: 4730183,name: "A A", source:"CRM", company: "NE Company"};
Basically, I want to find customer_source_id in the object and replace it with source.
I can't use indexOf and splice because the object is not an array.
What is the best way to do this? Do I have to convert it to an array first and then back again?
A quick answer would be:
var obj = {id: 4730183,name: "A A", customer_source_id:123, company: "NE Company"};
var json = JSON.stringify(obj);
json = json.replace("customer_source_id","source")
The better answer is:
#Waqar Ahmed is correct. JavaScript objects are unordered. In your example "var json" is an object not JSON. You can make it JSON with JSON.stringify(json). But once the JSON is parsed into an object it again becomes unordered. You should not use it to store ordered data.
I am not sure if it is efficient, but you can iterate through the keys and build a new json object like this:
var newjson = {};
for(var key in json){
if(key === 'customer_source_id'){
newjson.source = [NEW VALUE TO DISPLAY];
}else{
newjson[key] = json[key];
}
}
json = newjson;
But, like #Waqar and #Spencer said, the object is not used for ordered data.
You can do his only in java script array. Not in JSON. JSON is meant to be addressed by keys, not by index.Change your json to
var json ={id: 4730183,name: "A A", customer_source_id:null, items : [] company: "ESI"};
Now you can insert items using push method of array.
json.items.push('My Item');

Resources