Suppose we have a form that can contain an array of values.
For this case Angular provides us with FormArray class.
this.form = new FormGroup({
addresses: new FormArray([]),
})
Also we have an ability to use NgForm#setValue. This can be used i.e. to populate the form with some data retrieved from server.
When I receive new data from the server, I want to populate the form with that data. For example, my data looks like this:
const data = {
addresses: [
{ country: 'USA', city: 'New York' },
{ country: 'Germany', city: 'Berlin' },
]
}
Now it's time to populate the form with this data.
When I try to simply invoke this.form.setValue(data) I get an error:
Cannot set property stack of [object Object] which has only a getter
How do I populate the form with data, but with these requirements:
I know the shape of addresses property.
I don't know the quantity of addresses in that data.addresses array.
Try like this below
this.form.setControl('addresses', this.formBuilder.array(this.data.addresses || []));
Related
I have a property details which is a nested object.
On clicking sign-in i get a form object which has values i want to set the values from the form into the nested object. Why cannot we use the normal .(dot) operator or the [] to chain and access the nested objects and their properties.
export class AppComponent {
details:{
city:string,
dates:{
date:Date,
data:{
name:string,
comment:string
}[]
}[]
}
// this function is executed on submit of the form
onSignin(form:NgForm){
console.log(form)
this.details.city=form.value.city; // cannot set property 'city' of undifined
console.log(this.details)
}
}
I dont see any problem with your structure or code. It is possible that you may not be assigning the value correctly.
The below code gives me the correct output:
class Example {
details: {
city: string,
dates: {
date: Date,
data: {
name: string,
comment: string
}[]
}[]
} = {
city: "Tokyo",
dates: [
{
date: new Date(),
data: [
{
name: "Stackoverflow",
comment: "Hi"
}
]
}
]
}
getDetails() {
console.log(this.details.city)
this.details.city = "Hong Kong";
console.log(this.details.city)
}
}
new Example().getDetails();
This first prints "Tokyo" and then "Hong Kong".
You have just defined details as variable and not assigned any value. Since details is currently undefined, you cannot directly set the value of only one its nested objects. You can set value for city, if details was assigned to any non null value.
As the error message suggests, this.details is undefined. You need to create the object before you can set its properties. For example:
// A cast is required because `this.details` doesn't yet have the required properties.
this.details = {} as any;
this.details.city = form.value.city;
// ...
Or use an object literal instead of setting individual properties:
this.details = {city: form.value.city, dates: [ /*...*/ ]};
I have input with the name profile that is basically binded from data as:
data: function() {
return {
profile: {
phone: +123 123 123;
}
}
}
In the input I specify name as profile and v-model as profile.phone. It is sent to backend in the format:
name: profile, value: +123 123 123.
I obviously need to get also the information of the field specified - the phone. It is usually performed by sending name as profile.phone but the backend expects it as:
name: profile
value: {phone: +123 123 123}
The data are sent by sending all data from data. If I want to perform the reformatting that, how do I do that?
I recommend using re-declaring your object with let & this keywords. This will allow you to declare the owner of the function. so you can re-format as:
let profileValue = {
name: 'profile',
value: {
phone: this.profile.phone
}
}
You are sending the data to your back-end server using probably #click event that triggers your POST method? ...
Inside your method you need to construct your object like this...
let profileObj = {
name: 'profile',
value: {
phone : this.profile.phone
}
}
In a project I am working on, after obtaining a list of objects from an HTTP "get" request, one of the fields for each object is a string containing a status, "DEAD", "IDLE", etc. Is there any way to edit the structure of the object that comes in the list so it contains a few more fields based on that status value? For example, after the transformation each of the objects in the list would have the boolean fields isDead, isIdle, etc. Is this what the transformResponse() method in Angular does?
You can do something like this.
private getData(): void {
this.http.get('https://reqres.in/api/users?page=2').pipe(map((res: any) => {
return res.data;
})).subscribe((data) => {
this.data =data.map((item) => {
return {
id: item.id,
first_name: item.first_name,
last_name: item.last_name,
avatar: item.avatar,
age: 50
}
});
});
};
In here UI am requesting for a list of data and for each of the items in the list I am appending a age attribute.
You can find a working example in here
I have an event I'm storing in my database. It is stored as
events
my_party123
info
-KZbdiR_PBrAwxYvUR4U
name: 'John'
city: 'Los Angeles'
my_party124
...
However, I'm trying to retrieve this info and I can't quite get it.
I tried
ref
.child('events')
.child('my_party123') // I also tried .push('my_party123')
.once('value')
.then(snapshot => {
console.log(snapshot.key) // my_party123
console.log(snapshot.val().info)
// this shows object with
// "-KZbdiR_PBrAwxYvUR4U" property, this is the pushed key property
im trying to access
})
.pushed is creating new keys when i called it - how do i just access the value stored in my database?
If you're looking to have unique event URLs that point at events, I'd recommend a change to your data structure to be something more like:
events
-KZ123PUSHID
name: 'John'
location: 'Los Angeles'
-KZ124PUSHID
name: 'Morgan'
location: 'New York City'
eventNames
my_party_123: '-KZ123PUSHID'
sweet_nyc_part: '-KZ124PUSHID'
Then, in your code, you could do something like:
var eventNamesRef = firebase.database().ref('eventNames');
var eventsRef = firebase.database().ref('events');
var event;
eventNamesRef.child(nameFromUrl).once('value').then(nameSnap => {
eventsRef.child(nameSnap.val()).on('value', eventSnap => {
event = eventSnap.val();
});
});
Basically I got my app up an running but I'm stuck with a problem: if I pass an object that contains an empty array to be saved, the array is not saved into the db. I'm not sure this is a problem in js or the mongo driver, but in order to save the empty array I need to pass the array like so: products: [''].
This is the structure of my mongo document:
_id: ObjectId(...),
name: 'String',
subcategories: [
{
subcategory: 'string',
products: [
{
name: 'string'
price: integer
}
]
}
]
So in my front-end I'm grabbing the whole document through an ajax call pushing a new object into the subcategories array. The new object looks like this:
{subcategory:'string', products:['']}
And this works okay until I need to insert a new object inside the array: Because I've grabbed the whole object, pushed the new object to the array, the previous one looks like this:
{subcategory: 'string'}
Having lost the mention to products:[] array in the process.
How can I get around this? I need to be able to have empty arrays in my object.
EDIT
What I did on front end: Got the whole object with $.get which returned:
var obj =
_id: ObjectId(...),
name: 'String',
subcategories: [
{
subcategory: 'Subcategory1',
products: [
{
name: 'string'
price: integer
}
]
}
];
Then on the front end I've pushed the new object category inside the subcategories array:
data.subcategories.push({subcategory: 'Subcategory2', products: ['']})
Where subcat was a string with the category name. On my db I could see that I've successfully added the object:
var obj =
_id: ObjectId(...),
name: 'String',
subcategories: [
{
subcategory: 'Subcategory1',
products: [
{
name: 'string'
price: integer
}
]
},
{
subcategory: 'Subcategory2'
products: []
}
];
The problem was when I wanted to add another subcategory, the previous one return empty:
var obj =
_id: ObjectId(...),
name: 'String',
subcategories: [
{
subcategory: 'Subcategory1',
products: [
{
name: 'string'
price: integer
}
]
},
{
subcategory: 'Subcategory2'
},
{
subcategory: 'Subcategory3'
products: []
},
];
Because at some point the empty array was removed from the object. Like I said, I did fix this in the front end, so the error jade was throwing has been addressed, but I still find odd that the products: [] was being removed from the document.
I'm new to MongoDb and node, not to mention that I'm also new with JS, so it might well be a feature that I'm unaware of.
When passing empty arrays to Mongo they are interpreted as empty documents, {}. Zend Json encoder will interpret them as empty arrays []. I understand that it's not possible to tell which one is correct.
Incase of empty arrays try posting as
Array[null];
instead of Array[];
This will be working fine
When passing empty arrays to Mongo they are interpreted as empty documents, {}. Zend Json encoder will interpret them as empty arrays []. I understand that it's not possible to tell which one is correct.
In my view it's more logical that the actual php array (when empty) is interpreted as an array in MongoDB. Although that will require something else to identify empty documents it's still more logical than the current behaviour.
A possible solution would be to introduce a new object, MongoEmptyObject (or using the stdObj) whenever one want to introduce an empty object.
Meanwhile, a workaround is to detect empty arrays in php, and inject a null value $arr[0] = null;
Then the object will be interpreted as an empty array in mongo.
The workaround works both in PHP and in the mongo console. Question: does json allow for arrays with null values? If so, then the workaround is a sign of another bug.
PHP:
if (is_array($value) && empty($value))
{ $value[0] = null; }
Mongo Console:
var b =
{hej:"da", arr: [null]}
db.test.save(b);
db.test.find();
{"_id" : "4a4b23adde08d50628564b12" , "hej" : "da" , "arr" : []}