Simple way of updating an existing map within a List, or appending if it doesn't - immutable.js

I might be overthinking this, but is there an easy way to merge a change into an existing Map if it exists in a List, otherwise create a new Map at the end of the List?
Something like the following?
let mapToUpdateOrInsert = new Map({id: 1})
list.update(list.findIndex((map) => {
return map.get("id") === mapToUpdateOrInsert.get("id")
}), (update) => {
return update.merge({something: changed})
})

Related

How to delete all in json server

I am using this json server in my Angular app, to create, fetch, and delete posts.
In the following method, I delete a post with a specified id:
deleteConsumer(post: Post): Observable<Post> {
const url = `${this.apiUrl}/${post.id}`;
return this.httpClient.delete<Post>(url);
}
I looked at the .delete code and searched for something like a .deleteall but could not find it. Is there really no such method that would delete everything?
If there really isn't, then my attempt at doing it myself is not paying off, because what I have done is not working:
deleteConsumers(): Observable<Post> {
let i: number = 0;
this.httpClient.get<Post[]>(this.apiUrl).forEach(
() => {
++i;
const url = `${this.apiUrl}/${i}`;
return this.httpClient.delete<Post>(url);
}
);
}
Obviously, this is wrong in terms of return type, but I cannot figure out what to do... How can I modify the first method, so it would go through all the json objects in my db.json file; meaning iterate through all the existing posts and delete them all?
I did encounter this when using json-server with Vue.js and I realized that there was no special function to delete all at once. I had to work around it.
So, for example in your case, I would first map the posts array to get a new array with only the post ids:
const postsIdsArray = this.posts.map((post) => post.id)
Then, assuming you already have a function to delete one post given the id, I would then execute the function for each of the ids in the array:
postsIdsArray.forEach((id) => this.deletePost(id))
Just combine the two lines in one JavaScript function (in this case I used Vue.js):
deleteAllPosts(){
const postsIdsArray = this.posts.map((post) => post.id)
postsIdsArray.forEach((id) => this.deletePost(id))
}

Sequelize raw queries TextRow and getting data out of it

Given this query here,
let output = [];
const sql = `select * from coredb.account LIMIT ${offset},${limit}`;
let data = await sequelize.query(sql, null, {raw: true, type: sequelize.QueryTypes.SELECT});
data.forEach((item) => {
console.log(item['id'], item.id); // <-- output says "undefined, undefined"
});
the data variable is indeed hydrated with the right row data when using console.log to inspect it.
But, when I try to access the individual properties, they only ever come back as undefined. This TextRow object that Sequelize seems to return the result in doesn't seem to want to let me access then explicit rows.
Just curious what i'm missing here, am I missing an option?
I agree, Sequalize raw queries are not intuitive. You don't need the null or raw: true flag. Something like this should work:
let data = await sequelize.query(sql, {type: sequelize.QueryTypes.SELECT});
When I tried this, "data" was an array of two objects, each being the query result. So, the properties can be accessed by using index [0].... e.g.
data[0].forEach((item) => {
console.log(item['id'], item.id); // <-- output says "undefined, undefined"
});
Not yet sure WHY this occurs!
EDIT - it's because .query() should have only two arguments. Changing the call to: sequelize.query(sql, {raw: true, type: sequelize.QueryTypes.SELECT}) resulted in data being a single array (as expected).
Finally I was able to find the solution for it.
You just need to make a new array and push data into it by finding bases on key name like this:
suppose we have data in students object:
let finalArray = new Array();
for (var k in students ) {
finalArray.push(students[k])
}
console.log(finalArray) // Normal JSON array object :)
m.sequelize.query(sql, {
model,
mapToModel: true
})
.then(model => res.status(200).send(model))
.catch(error => res.status(400).send(error.toString())
})

Unable to add new key-value pair dynamically to a STATE JSON Array in React App

I am trying to add a new key-value pair to the already loaded JSON Array. I am adding the new key-value pair to customize the header column cells in react bootstrap table but getting the below errors. Can any one please help?
'Columns' in the below state is where I wanted to add new key-value pair
state = {
data: MYResult.Products || [],
actualData: MYResult.Products || [],
columns: MYResult.ParametricList_Attributes || [],
isCompareClicked: false,
isDisabled: true,
selected: []
};
This is how I am adding the key-value pair -
componentDidMount(){
checkbox = (column, colIndex) => {
return (
<h5>{ column.text }<checkbox/></h5>
);
}
console.log(this.state.columns) ;
newColumn = this.state.columns.map((column) => {
return {...column, headerFormatter: checkbox};
});
this.setState({columns: newColumn });
}
Full code here - https://codesandbox.io/s/o1r988qkz Please uncomment the componentDidMount() to see the issue
Firstly, there's a typo in dcolumn and column.
And regarding the not defined error, you need to define it using const. Use like:
const checkbox = (column, colIndex) => {
return (
<h5>{column.text}<checkbox /></h5>
);
}
JavaScript variables need to be declared when they are used. Public class syntax can not be used everywhere. The error you're getting is self-evident - 'checkbox is not defined'.
Refer this on how to use it: https://tylermcginnis.com/javascript-private-and-public-class-fields/
I simply declared the undeclared variables in your example and the code worked.

RxJs Interval with takeUntil to publish last value

I have some code which polls until a task is complete
See below
this.simulationStatus =
interval(2000).pipe(
switchMap(
() => from(this.simulationService.getSimulationStatus(this.route.snapshot.paramMap.get('jobId')))),
takeUntil(this.stopPoll),
tap(simulation => {
if (simulation && simulation.complete) {
if (this.stopCount == 1) {
// Get once after complete
this.stopPoll.next(true);
}
this.stopCount++;
}
})
);
I have tried using takeUntil and takeWhile the problem is that that the last value is never published once the task is complete.
To get around this I have to include the tap method to with the stopPoll subject and incrementing the stopCount to get the last value.
So the above works but just feels a bit messy, I'm sure there must be a better way of achieving this?
I would have expected takeUntil to publish the last value or have an override to tell it to e.g takeUntil(observable, {publishLast: true})
BTW Update, the observable is subscribed to by an Angular 6 template
Thanks in advance
One thing you can do is use a custom takeWhile-like operator like this:
const completeWith = <T>(predicate: (arg: T) => boolean) => (
source: Observable<T>,
) =>
new Observable<T>(observer =>
source.subscribe(
value => {
observer.next(value);
if (predicate(value)) {
observer.complete();
}
},
error => observer.error(error),
() => observer.complete(),
),
);
It doesn't seem like a good idea to see it as a variation of takeWhite because it's not just taking values while a condition holds, but also emits an extra value.
It might be that a more elegant solution would be make the simulation status observable emit two kinds of values: next notifications and completion notifications, similarly to how materialize/dematerialize operators work.
This has in the meantime been implemented in rxjs as takeWhile(condition, ?inclusive):
timer(0, 10).pipe(
takeWhile((x) => x < 3, true)
)
emits 0, 1, 2, 3
You can also create subject and emit using next() if you want to complete the observable.
this.stopPoll: Subject<any> = new Subject<any>();
If you want to do complete the subscription. you can call this.stopPoll.next(true);
you can access the data in subscribe()
this.simulationStatus.subscribe(success=>{}, failure=>{}, complete=>{});

Help building up LINQ query when using anonymous types

I've started out with:
IQueryable<Author> authors2 = db.Authors;
Then I build up authors2 in multiple if statements, here's one of them
authors2 = authors2.Where(t => t.ItemAuthors.Any(b => b.Item.CategoryItems.Any(z => z.categoryID == int.Parse(ddlCategory.SelectedValue))));
Then finally I would like to append this to the end of the built up where clauses
authors2.OrderBy(x => x.text).Select(x => new
{
authorText = string.Format("{0} ({1})",x.text, x.ItemAuthors.Count())
});
To bind a control like this:
ddlAuthor.DataSource = authors2;
ddlAuthor.DataTextField = "authorText";
ddlAuthor.DataBind();
Apparently the compiler is not very happy about my select new statement. How can I rewrite this to achieve the same goal? I believe this is called creating an anonymous type.
It says an explicit conversion exists(are you missing a cast?) I can't figure out how to cast it.
In your third statement, the returned type is not same as authors2 because the Select projects a different type other than Author
So assign the value to a new variable
var authorsFinal = authors2
.OrderBy(x => x.text)
.Select(x => new
{
authorText = string.Format("{0} ({1})",
x.text,
x.ItemAuthors.Count())
});