So I'm having an issue with my create method in my angular. I'm using django for my backend, and I doublechecked, everything is working in the backend, with postman. Anyways here's the error. When I try to make a post request, this is the error that I get in the console. Below oyu may find the product that is sent from my end.
Note: This may not be the ideal approach to the overall problem, but it does answer the immediate question at hand.
As the error states you need to pass in an array (irrespective of how many categories are selected) rather than a string. Make the following change:
onSubmit() {
const formValues = Object.assign({}, this.productForm.value);
productForm["product_category"] = productForm["product_category"]
.split(',').map(e => e.trim());
}
Here, the product_category from formValues is fetched and the string is split based on , which results in an array - to which empty spaces are removed and assigned back as the new value to product_category.
Related
I'm working with JavaScript in Node.js and using Express with some mongoose and following a well known RESTful API tutorial on youtube, I've come to patching the API and have been trying to understand why the following code works for sometime now;
updateItem = {};
for (const changes of req.body) {
updateItem[changes.propName] = changes.value;
}
Product.updateOne({ _id: id }, { $set: updateItem })
The rest is just your standard .then().catch() to send the response status, but I'm lost on how creating the object then placing it before an array works to update a value.
It's my current understanding that the object must be instantiated before use, I couldn't just put brackets there and have it work, even if I wasn't using it to set something later. Then I loop through the changes from the request body which must be an array to allow looping, but here's where I get lost.
Does the array of iterated prop names changes.propName get placed inside the updateItem object which is then set to the changed values from the array of properties that are being changed? Do I need to understand $set syntax more? I'm struggling to pick it apart to make it longer or simpler but better to understand.
This is the json array setup I'm passing for testing through postman if it helps;
[
{
"propName": "name", "value": "placeholder user"
}
]
I was unable to find anything to help me understand the interactions going on here, I haven't seen something like this before either but please redirect me if this has already been asked.
I have a condition call. To check condition you need to call other endopint. What is better api design?
e.g
if(fetch('api/is-data-valid')){
const data = fetch('api/get-profile-data');
// do something with data
}
or
const data = fetch('api/get-profile-if-data-valid');
if(data.isDataValid) {
// do something with data
}
If the client can't work out whether the data is valid, the API should respond accordingly, without an extra step.
Instead of checking api/is-data-valid to get api/get-profile-data, do it in one request, which hides the implementation suggested by api/get-profile-if-data-valid
You can only get profile-data if the data is valid so let the API work it out.
fetch('api/get-profile-data'); // returns profile data or 404
and let the client concentrate on displaying an error saying the data is invalid because the corresponding profile doesn't exist.
The answer depends on a few things. In general it's best to keep the number of api calls to a minimum so doing one call instead of two is preferable. However if there are cases that someone would want to check if data is valid without getting the profile, then having the is-data-valid api is important.
My advice would be to have both api's but allow someone to call get-profile-data when it's invalid and handle that case in a well defined way. This would allow the work to be done with a single call, but still allow other use cases where checking the data validity is useful on its own.
Hi I have a form in Angular, that i build with values from an Observable from API.
.subscribe((res) => {
this.data = res['attributes'];
});
//this.data is array of objects!!
this.attribs = modifyClean(this.data);
this.attribsOriginal = this.attribs;
Object.freeze(this.attribsOriginal);
After the form is built with this.attribs. If the user edits its original form values and Clicks save, the api saves it.
But if the API fails to save (500 error or something) I want the form to go back to its original values.
I am not using Reactive forms on purpose. But here is what i am doing when the api fails in error code
,error {
this.attribs = this.attribsOriginal;
}
But this is not replacing the form values with original values. It is retaining the values. I console.log both this.attribs and this.attribsOriginal in error block. Both of them are same values. How is this possible. I froze attribsOriginal.
If i say this.attribs = []; the form is completely removed as expected.
But why doesnt this.attribs = this.attribsOriginal, replace the form values with orginal values.
I thought freezing this.attribsOriginal will have no impact no matter what you do to this.attribs.
what can be done to avoid this situation?
It looks like this.attribs is a reference to data returned by modifyClean(this.data), and this.attribsOriginal is also a reference to the same data. If you're trying to clone an object this looks helpful
Angular uses change detection to decide when to build/rebuild the portion of the dom using your "this.attribs" data. Since nothing is changing it isn't building/rebuilding the dom.
I think you could try arbitrarily changing the data in the component.ts file, and changing it back, or this might be helpful
UPDATE 1: 5 votes have been received, so I have submitted a feature request: https://github.com/LearnBoost/mongoose/issues/2637
Please cast your +1 votes there to let the core team know you want this feature.
UPDATE 2: See answer below...
ORIGINAL POST:
Lets say I do a "lean" query on a collection OR receive some data from a REST service and I get an array of objects (not mongoose documents).
These objects already exist in the database, but I need to convert some/all of those objects to mongoose documents for individual editing/saving.
I have read through the source and there is a lot going on once mongoose has data from the database (populating, casting, initializing, etc), but there doesn't seem to be a method for 'exposing' this to the outside world.
I am using the following, but it just seems hacky ($data is a plain object):
// What other properties am I not setting? Is this enough?
var doc = new MyModel( $data );
doc.isNew = false;
// mimicking mongoose internals
// "init" is called internally after a document is loaded from the database
// This method is not documented, but seems like the most "proper" way to do this.
var doc = new MyModel( undefined );
doc.init( $data );
UPDATE: After more searching I don't think there is a way to do this yet, and the first method above is your best bet (mongoose v3.8.8). If anybody else is interested in this, I will make a feature request for something like this (leave a comment or upvote please):
var doc = MyModel.hydrate( $data );
Posting my own answer so this doesn't stay open:
Version 4 models (stable released on 2015-03-25) now exposes a hydrate() method. None of the fields will be marked as dirty initially, meaning a call to save() will do nothing until a field is mutated.
https://github.com/LearnBoost/mongoose/blob/41ea6010c4a84716aec7a5798c7c35ef21aa294f/lib/model.js#L1639-1657
It is very important to note that this is intended to be used to convert a plain JS object loaded from the database into a mongoose document. If you are receiving a document from a REST service or something like that, you should use findById() and update().
For those who live dangerously:
If you really want to update an existing document without touching the database, I suppose you could call hydrate(), mark fields as dirty, and then call save(). This is not too different than the method of setting doc.isNew = false; as I suggested in my original question. However, Valeri (from the mongoose team) suggested not doing this. It could cause validation errors and other edge case issues and generally isn't good practice. findById is really fast and will not be your bottleneck.
If you are getting a response from REST service and say you have a User mongoose model
var User = mongoose.model('User');
var fields = res.body; //Response JSON
var newUser = new User(fields);
newUser.save(function(err,resource){
console.log(resource);
});
In other case say you have an array of user JSON objects from User.find() that you want to query or populate
var query = User.find({});
query.exec(function(users){
//mongoose deep-populate ref docs
User.deeppopulate users 'email_id phone_number'.exec({
//query through populated users objects
});
});
MongoDB doesn't support Joins and Transfers. So for now you can't cast values to an object directly. Although you can work around it with forEach.
I'm trying to get the number of results of the Ember Data Store filter. E.g
var users = this.store.filter('relevantUser', function(user)
{
return user.get('screenName') == screenName;
});
return user.get('length');
But this always seems to return 0. What am I doing wrong?
I think it should be users.get('length');.
Things to make sure when using filter method of the store.
First argument is the model type. Assuming you have a model named App.RelevantUser then your query is fine, else if the model is App.User then you should be using 'user'.
The var users is actually a DS.PromiseArray instance and not an array actually. Try doing this
this.store.filter('relevantUser',function(user){return user.get('screenName')==screenName}).then(function(relevantUsers){console.log(relevantUsers.get('length'))})
As store.filter queries the server too we need to wait for the promise to resolve before accessing the results. Otherwise they would be always 0.
Incase you are using Chrome. Open up Network Tab in Dev Tools and check the network request going to the server when you run the filter query.