Bind form field to an object after ngInit has run angular 2 in reactive forms - forms

We are using a component that contains a form. We don't want to bind the fields to any specific model at initiation because we want to be able to use it against multiple interfaces.
We are using it as a multiple instance component in a parent componen, like the following example:
<component>
<foo1></foo1>
<foo2></foot2>
<component>
Assuming that the foo subcomponents contain a form with the field Name
From the parent component, we would like to bind (for example) the Name field in foo1 to object.foo1.form.name and object.foo2.form.name
But this has to happen in the ngAfterViewInit event.
The API says that there is a model property on the formcontrol directive. But can you access that property after post ngInit? If so, how?

Related

Thymeleaf form with multiple objects of the same class

Simple problem but can't find a solution: I have a Thymeleaf form used to add a new object, say of a Book class. It works perfectly well and I only need that particular form for adding new objects, not editing the existing ones. The question is: how can I put several objects of the Book class in the same single form? So, purely for convenience, instead of filling form for a single book and clicking Send you can fill form for several books at once and only then click Send, have them all inserted into the database (in whatever order) and also have the option to fill the form partially (e.g. the form has room for 5 books but it will also accept 1, 2, 3 or 4 and you can leave the rest blank).
Edit: I've tried passing a list of object to the Thymeleaf template with the form bound to the whole list and iteration inside, but Thymeleaf throws BingingResultError upon rendering it.
You need to use a wrapper object to realize what you want.
Something like:
public class BooksCreationDto {
private List<Book> books;
// default and parameterized constructor
public void addBook(Book book) {
this.books.add(book);
}
// getter and setter
}
Then you need to pass this object as a model attribute in your controller:
BooksCreationDto booksForm = new BooksCreationDto();
model.addAttribute("form", booksForm);
bind fields using index property
th:field="*{books[__${itemStat.index}__].title}"
and get back the result with
#ModelAttribute BooksCreationDto form
in your controller.
For a complete and detailled explaination visit: https://www.baeldung.com/thymeleaf-list

Placing a component containing a formGroup in a formGroup (data-driven from Angular2)

I've got 2 components:
the first component is a formGroup for user details
the second component is should be nested as an address formGroup, user formGroup
the selectors are:
- <ts-user></ts-user>
- <ts-address></ts-address>
Since a user can have more than one address and I would like to make the address component containing the form reusable. I'd like to know how to nest the address component in the user's component. Like this:
<ts-user>
<ts-address></ts-address>
</ts-user>
Clearly, placing the address selector in the user selector does not create any error, but I'd like to know how to make validation work on both.
Any full/pseudo-code or any tutorial to "enlight" me would be of great help.

Angular2 model-based parent/children form

I'm a newbie with Angular2 (beta1) and I'd like to implement a sort of simple editable grid, built of 2 components. Here I use two fake-data components to keep things simple. They are (see this Plunker: http://plnkr.co/edit/5cZfLTIlhLc82wWV4PQI):
the parent component, named contact. Say it represents a contact with a name.
the child component, named entry. Say it represents an entry for a contact, where each contact can include 0 or more entries. Each entry has an address and a zip code.
I'd like to create a form where the user can edit the contact's properties, and also its children entries: he could add a new entry, delete an existing entry, or edit an existing entry.
To this end, the views for both these components provide a form-based template.
I can think of this data flow:
contact: the user edits the form and then clicks a submit button to save
the whole thing. Thus, I can just have some code handling the submit button
and emitting an event as the component output. The contact has an entries
array property: I can thus use an ngFor directive in its template to render
an entry component for each of them.
entry: the entry has properties addressCtl and zipCtl which represent
the control directives included in the ControlGroup representing the whole
form. Also, I need a couple of properties to be bound as the input of the
component (address and zip), so that in the parent template I can do something like:
<tr *ngFor="#e of entries">
<td><my-entry [address]="e.address" [zip]="e.zip"></my-entry></td>
</tr>
Now, it's not clear to me how to shape the relation between the "model" properties representing the control's input, and the "form" directives properties. I should be able to get the address and zip values from the parent component through the [...] binding, and pass the updated values up through an event fired by the child component (e.g. blur?). Does this make sense in the NG2 world? Anyway, I'm missing a piece here: how can I connect the form controls values to the model properties values? Could anyone make this clearer or point to some good docs?
In fact, using the [...] binding only corresponds to a one-way binding. When the parent property is updated in the parent component, the value is also updated in the child component.
But if you want to update parent attributes from the child, you need to leverage events and #Ouput attribute.
Here is a sample with a labels component:
export class LabelsComponent implements OnInit {
#Input()
labels:string[];
#Output()
labelsChange: EventEmitter;
(...)
removeLabel(label:string) {
var index = this.labels.indexOf(label, 0);
if (index != undefined) {
this.labels.splice(index, 1);
this.labelsChange.emit(this.labels);
}
}
addLabel(label:string) {
this.labels.push(this.labelToAdd);
this.labelsChange.emit(this.labels);
this.labelToAdd = '';
this.addAreaDisplayed = false;
}
}
This way you can leverage two way binding on this component:
<labels [(labels)]="company.labels"></labels>
Hope it answers your question,
Thierry
Just moved the comment to answer...
You can pass the object e, instead of passing string.
i.e
<my-entry [entry] = "e"></my-entry>
then in your my-entry component, use ng-model for each input. so you automatically gets 2 way bindings.

querySelect angular component as MyComponent

I have an angular component
<my-component foo="" bar=""></my-component>
And its corresponding class MyComponent
I use this component in my html
<my-component foo="bar" bar="foo"></my-component>
<my-component foo="baz" bar="qux"></my-component>
<my-component foo="bar" bar="baz"></my-component>
Now i want to querySelect my custom elements and access their attributes directly. I think about something like this:
List<MyComponent> mys = querySelector('my-component');
mys.forEach((my){
print(my.foo);
my.bar = '1234';
});
There are a view problems with that code:
querySelector always returns Element not MyComponent. can i cast Element to MyComponent?
Is MyComponent to <my-component> like DivElement to <div>?
querySelector cannot select custom elements. i could ad a class to every my-component and select it with that class. or is there another way?
I only can access the attributes with my.getAttribute() not with my.foo. I know, this is because my is still a Element not a MyComponent.
This is not officially supported. There was something like ng-element that allowed this as far as I remember but was intended to be only used for unit tests. There were some changes in the last versions but I don't know the current state.
You should pass references using dependency injection, Angular events (explained here How to communicate between Angular DART controllers) or the scope to access other elements.

Pass a bean like a property of another bean (struts 1.x)

I have two forms (and the corresponding form beans), one on page1.jsp and another on page2.jsp (this second form is dinamically created via json). The form1 is of mypackage.MyActionForm1 type, while the form2 is of mypackage.MyActionForm2 type. In the Action executed when the first form is submitted, I create a MyActionForm2 and set the MyActionForm1 form as its property:
MyActionForm2 secondBean = new MyActionForm2();
secondBean.setBeanProp(form1);
request.setAttribute("secondbean", secondBean);
In the jsp I succeed in accessing the properties of form1:
${secondbean.beanProp.prop1}
but how pass the first bean to the Action executed when the second form, form2, is submitted?
form2.getBeanProp().getProp1() // form2.getBeanProp() gives a NullPointerException
I wouldn't to use session scope.
If you don't have a hidden field for every property of your form2.getBeanProp() bean, then obviously Struts won't be able to reconstruct this bean from thin air.
To be able to populate the property prop1 of the bean returned by actionForm.getBeanProp(), you need a hidden field named beanProp.prop1. If you don't want to have the whole state of beanProp in your HTML form as hidden fields, then store this bean in session.