I have a Typescript class in which I collect a JSON Object with some empty parameters, what I want is to filter that object to obtain another Object but without the empty data of the first one.
This is my JSON object:
{ Country: 'Colombia',
Ser: 'ok',
Ins: '',
BBDD: 'ok',
Mid: '',
Ata: '',
'Branch Ser': 'ok',
Service: '' }
This is what I want to achieve:
{ Country: 'Colombia',
Ser: 'ok',
BBDD: 'ok',
'Branch Ser': 'ok' }
const allData = {
Country: 'Colombia',
Ser: 'ok',
Ins: '',
BBDD: 'ok',
Mid: '',
Ata: '',
'Branch Ser': 'ok',
Service: ''
};
const filteredData = Object.entries(allData).reduce((x, [k, v]) => {
if (v) { // not ( null, undefined, empty string)
x[k] = v;
}
return x;
}, {} as any);
console.log(filteredData);
You can use Object.entries function to list object as key value pairs and then use the Array.reduce to filter out the falsy values.
const allData = {
Country: 'Colombia',
Ser: 'ok',
Ins: '',
BBDD: 'ok',
Mid: '',
Ata: '',
'Branch Ser': 'ok',
Service: ''
};
const filteredData = Object.fromEntries(Object.entries(allData).filter(([_, value]) => value));
console.log(filteredData);
Above is a simple one-line solution to do it. Using JS' Object.fromEntries() really helps.
Related
I am using: Laravel, Vue JS, dropzone.
Works fine with one file being uploaded but when 3 files are uploaded it create a new homework record, like so:
Homework ID: 1, Files: 1, 2
Homework ID: 2, Files: 3
Should look like:
Homework ID: 1, Files: 1,2,3
Code for upload is the following:
public function store() {
$data = request()->validate([
'title' => '',
'description' => '',
'start_date' => '',
'due_date' => '',
'group_id' => '',
'dropzonefile' => '',
'live_status' => '',
]);
// Create homework record...
$task = request()->user()->homeworks()->create([
'title' => $data['title'],
'description' => $data['description'],
'start_date' => $data['start_date'],
'due_date' => $data['due_date'],
'live_status' => $data['live_status'],
]);
// Add homework to some groups...
$task->groups()->attach(Arr::pluck(json_decode($data['group_id']), 'group_id'));
// Upload all files...
if (isset($data['dropzonefile'])) {
foreach ($data['dropzonefile'] as $attachment) {
$attachmentName = $attachment->store('userFiles', 'public');
$attachmentInfo = request()->user()->attachments()->create([
'reference_name' => $attachmentName,
'original_file_name' => $attachment->getClientOriginalName(),
]);
$task->attachments()->attach($attachmentInfo->id);
}
}
return new TaskResource($task);
}
Front End Code:
dropzoneOptions: {
paramName: "dropzonefile",
url: '/api/homework',
thumbnailWidth: 150,
maxFilesize: 20,
maxFiles: 5,
addRemoveLinks: true,
uploadMultiple: true,
autoProcessQueue: false,
headers: {
'X-CSRF-TOKEN': document.head.querySelector('meta[name=csrf-token]').content,
},
sending: (file, xhr, formData) => {
formData.append('title', this.taskTitle);
formData.append('description', this.content);
formData.append('start_date', this.selectedSetDate);
formData.append('due_date', this.selectedDueDate);
formData.append('group_id', JSON.stringify(this.value));
formData.append('live_status', this.liveStatus);
},
success: (event, res) => {
// alert('success');
console.log(event);
this.makeToast(true,'info');
this.$router.push('/Teacher')
}
},
I think I found the answer:
upload multiple files in one request Dropzone sending two requests
Seems like I was missing some dropzone options:
autoDiscover: false,
parallelUploads: 10,
I used a fetch API to get data from backend server. I returned JSON object data from fetch function and I want to pass every single value in the object to another object.
function getvals() {
return fetch('http://*********/users/timetable')
.then(response => response.json())
.then((responseData) => {
console.log(responseData);
return responseData;
})
.catch(error => console.log(error))
}
the function getvals() is returning the object data, these data looks like this:
[{"title": "Math","day": "FRI", "end_time": 11, "start_time": 9,location: "Classroom 403",extra_descriptions: "Chen"}]
now I want every single value of the object data to be passed to this object:
const events_data = [
{
title: "Math",
startTime: genTimeBlock("WED", 9),
endTime: genTimeBlock("WED", 10),
location: "Classroom 403",
extra_descriptions: ["Kim", "Lee"],
},
{
title: "Mandarin",
startTime: genTimeBlock("TUE", 9),
endTime: genTimeBlock("TUE", 10),
location: "Language Center",
extra_descriptions: ["Chen"],
},
{
title: "Japanese",
startTime: genTimeBlock("FRI", 9),
endTime: genTimeBlock("FRI", 10),
location: "Language Center",
extra_descriptions: ["Nakamura"],
},
];
for example the value of day from getvals() function i want to pass it to be set in in startTime in events_data object
then within the the view the events_data will be passed to events props:
<SafeAreaView style={{ flex: 1, padding: 30 }}>
<View style={styles.container}>
<TimeTableView
scrollViewRef={this.scrollViewRef}
**events={// events.data will be passed here as object format //}**
pivotTime={8}
pivotDate={this.pivotDate}
numberOfDays={this.numOfDays}
onEventPress={getvals}
headerStyle={styles.headerStyle}
formatDateHeader="dddd"
locale="en"
/>
</View>
</SafeAreaView>
it may the way to do this is easy but im new with this approche and i couldn't find an easy way to do it.
You can map over the data and then add them to the array events_data.
The function addData pushes the data received from the fetch request in the desired format to the events_data.
function getvals() {
fetch("http://*********/users/timetable")
.then((response) => response.json())
.then((output) => {
addData(output, events_data);
})
.catch((error) => console.log(error));
}
function addData(data, data2) {
data.forEach(d) => {
data2.push({
title: d.title,
startTime: genTimeBlock(d.day, d.startTime),
endTime: genTimeBlock(d.day, d.endTime),
location: d.location,
extra_description: [d.extra_description],
});
});
}
Edit:
If you wanted to render the data then you can do it like this:
const RenderData = () => {
return (
<View>
{events_data &&
events_data.result.map((data) => {
return <Text>{data.title}</Text>;
})}
</View>
);
};
On my api test, it was able to run as the image below. but, when I try to code in React.JS, the user Id cannot be pass in. What is the problem of this?
But when I try to code in front end, the user Id cannot be pass in to api.
Consider the code below:
constructor (props){
super(props);
const Users_id = localStorage.getItem('id');
this.state ={
users_id: Users_id,
event_name: '',
event_email: '',
event_description: '',
event_type: '',
event_location: '',
start_date: '',
end_date: '',
history: PropTypes.object.isRequired
}
this.create = this.create.bind(this);
this.onChange = this.onChange.bind(this);
}
create(){
// const loginEmail = localStorage.getItem('loginEmail');
const Users_id = localStorage.getItem('id');
this.setState({Users_id})
// console.log(loginEmail)
PostData('api/event/submit', this.state).then ((result) => {
let responseJSON = result;
console.log(responseJSON);
console.log(this.state)
});
}
The error show in console.log(responseJSON):
//Updated PostData
return new Promise((resolve, reject) => {
fetch( BaseUrl+type, {
method: "POST",
body: JSON.stringify(userData),
Accept: 'application/json',
// mode: 'no-cors',
headers:
{
'Content-Type': 'application/json'
},
})
.then((response) => response.json())
.then((responseJson) => {
resolve(responseJson);
})
.catch((error)=>{
console.error('Error:', error);
})
});
Storage.getItem returns a string. The id should be casted to a number
const Users_id = parseInt(localStorage.getItem('id'));
You may want to check isNaN(Users_id) before sending it. Or just let it fail, and handle the error.
you need to check if the user id exists in local storage before inserting it into props
super(props);
const Users_id = localStorage.getItem('id') || '';
this.state ={
users_id: Users_id,
event_name: '',
event_email: '',
event_description: '',
event_type: '',
event_location: '',
start_date: '',
end_date: '',
history: PropTypes.object.isRequired
}
and when you want to setState you need to pass the same name you used in the state
const Users_id = localStorage.getItem('id');
if(Users_id){
this.setState({users_id: Users_id})
}
Let's say I've got a web service that will return basic data as follows (result is named CustomerGroups):
{
0: {
Name: 'Group 1',
Customers: {
0: {
CustomerNo: 1,
Name: 'Customer 1'
},
1: {
CustomerNo: 2,
Name: 'Customer 2'
}
}
},
1: {
Name: 'Group 2',
Customers: {
0: {
CustomerNo: 3,
Name: 'Customer 3'
},
1: {
CustomerNo: 4,
Name: 'Customer 4'
}
}
}
}
Furthermore i've got a web-service that will return detailed customer data:
{
CustomerNo: 1,
Street: 'Test Street 123',
PostCode: '99999',
City: 'Blabla',
...
}
What I want to do is to combine the result of both services using a forkJoin in an Angular4 injectable service. But I stuck when I try to request each detailed information on a given customer:
ReadAll(useCache?: boolean): Observable<ICustomerGroup[]> {
if (!this.customerGroupCache || !useCache) {
return this.http.get(this.urlGetAll)
.map((res: Response) => res.json())
.flatMap((customerGroups: any[]) => {
if (customerGroups.length > 0) {
return Observable.forkJoin(
customerGroups.map((customerGroup: any) => {
return this.customerService.get(/* any CustomerNo of customerGroup.Customers */)
// ^---- This is my problem!!!
})
);
}
// No data! Return empty array
return Observable.of([]);
})
.catch((error: any) => Observable.throw(error.message || 'Server error'));
}
return Observable.of(this.customerGroupCache);
}
How can I use the forkJoin to loop over each CustomerGroup (flatMap used to do that) and get the detailed information for each Customer? Is it possible to use forEach inside a forkJoin?
The result of forkJoin should look like:
{
0: {
Name: 'Group 1',
Customers: {
0: {
CustomerNo: 1,
Name: 'Customer 1',
Street: 'Test Street 123',
PostCode: '99999',
City: 'Blabla'
},
1: {
CustomerNo: 2,
Name: 'Customer 2',
Street: 'Test Street 456',
PostCode: '888',
City: 'Blabla'
}
}
}
...
}
Solution
As per description by taras-d, I missed mergeMap to combine the results of multiple Observables. My final source looks like:
ReadAll(useCache?: boolean): Observable<ICustomerGroup[]> {
if (!this.customerGroupCache || !useCache) {
return this.http.get(this.urlGetAll)
.mergeMap((res: Response) => {
const customerObservables = [];
let groups = res.json();
groups.forEach((group, i) => {
group.Customers.forEach((cust, j) => {
customerObservables.push(this.customerService.get(cust.CustomerNo));
});
});
return Observable.forkJoin(customerObservables)
.map(customers => {
this.customerGroupCache = this.buildCustomerGroupArray(groups, customers);
return this.customerGroupCache;
});
});
}
return Observable.of(this.customerGroupCache);
}
Put it all together:
private buildCustomerGroupArray(allGroups: any, allCustomers: any): Array<ICustomerGroup> {
let result: Array<ICustomerGroup> = Array<ICustomerGroup>();
allGroups.forEach((group, index) => {
let newGroup = new CustomerGroup();
newGroup.ActionFlag = ActionType.Undefined;
newGroup.Name = group.Name;
newGroup.OldName = group.OldName;
newGroup.CustomerList = Array<ICustomerGroupItem>();
group.Customers.forEach((cust, index2) => {
if (allCustomers.find(p => p.CustomerNo === cust.CustomerNo)) {
let currCust = allCustomers.find(p => p.CustomerNo === cust.CustomerNo);
let newGroupItem: ICustomerGroupItem = new CustomerGroupItem({
ActionFlag: ActionType.Undefined,
CustomerName: currCust.Name,
CustomerNo: currCust.CustomerNo
});
newGroup.CustomerList.push(newGroupItem);
}
});
result.push(newGroup);
});
return result;
}
Easiest way is to get all groups and all customers and then combine them.
export class AppComponent {
// Fake customer service
customerService = {
getGroups() {
return Observable.of({
0: {
Name: 'Group 1',
Customers: {
0: {
CustomerNo: 1,
Name: 'Customer 1'
},
1: {
CustomerNo: 2,
Name: 'Customer 2'
}
}
},
1: {
Name: 'Group 2',
Customers: {
0: {
CustomerNo: 3,
Name: 'Customer 3'
},
1: {
CustomerNo: 4,
Name: 'Customer 4'
}
}
}
});
},
getCustomer(num) {
return Observable.of({
CustomerNo: num,
Street: `Street ${num}`,
PostCode: `PostCode ${num}`,
City: `City ${num}`
});
}
};
readAll(): Observable<any> {
// Get all groups
return this.customerService.getGroups().mergeMap(allGroups => {
const customersObservables = [];
// Loop over groups
for (let groupNum in allGroups) {
const group = allGroups[groupNum];
// Loop over customers in group
for (let customerNum in group.Customers) {
const customer = group.Customers[customerNum];
// Create observable for every group customer
customersObservables.push(
this.customerService.getCustomer(customer.CustomerNo)
);
}
}
// Join all customers observable and map (return) all groups and all customers
return Observable.forkJoin(customersObservables)
.map(allCustomers => [allGroups, allCustomers]);
});
}
ngOnInit(): void {
this.readAll().subscribe(res => {
// Here you will receive all groups and all customers
const [ allGroups, allCustomers ] = res;
console.log( JSON.stringify(allGroups, null, 2) );
console.log( JSON.stringify(allCustomers, null, 2) )
// TODO: Combine result
});
}
}
I have a array of data something like
var records = [
{Name: '', Id: 1},
{Name: '', Id: 2},
{Name: '', Id: 3},
{Name: '', Id: 4},
{Name: '', Id: 5},
{Name: '', Id: 6}
];
there could be thousands of items inside records array...
Ques1: Can we create a stored procedure which will accept an array of objects in mysql?
Ques2: Is there a way to bulk insert this data into mysql with Node JS?
You can bulk insert the array of records ,but before that you might need to convert it into array of arrays
I use array reduce to get an array something like this
let j=[
{Name: '', Id: 1},
{Name: '', Id: 2},
{Name: '', Id: 3},
{Name: '', Id: 4},
{Name: '', Id: 5},
{Name: '', Id: 6}
];
let values=j.reduce((o,a)=>{
let ini=[];
ini.push(a.Name);
ini.push(a.Id);
o.push(ini);
return o
},[])
console.log(values);
This will output
[["",1],["",2],["",3],["",4],["",5],["",6]]
Now inserting into the mysql database
1-Using normal callback
const con=require('./mysql.js'); //mysql connectionin mysql.js
var sql = "INSERT INTO customers (name, id) VALUES ?";
con.query(sql, [values], function (err, result) { //pass values array (from above) directly here
if (err) throw err;
console.log("Number of records inserted: " + result.affectedRows);
});
});
so the format of multiple data insert should be like [[[a,b],[b,c],[d,k]]]
2-Using promises
var Promise = require("bluebird");//for promises
const promisecon=Promise.promisifyAll(require('./mysql.js'));//
var sql = "INSERT INTO customers (name, id) VALUES ?";
promisecon.queryAsync(sql,[values]).then((result)=>{//bluebird identifies with Async
console.log(result);
}).catch(function(err){
console.log(err);
})
3-Using async await
var sql = "INSERT INTO customers (name, id) VALUES ?";
async function build() {
try {
const result =await con.queryAsync(sql,[values]);
console.log(result);
} catch (err) {
// do something
}
}
build();