How to push array of string in formArray? - javascript

I need to create this:
instructions: ['value one' , 'value two' , 'value three'];
I am using formArray and check my code on stackblitz first:
https://stackblitz.com/edit/formarray-obj?file=app/app.component.ts
html:
<div class="form">
<form id="form" [formGroup]="filmForm" (ngSubmit)="save()">
<button type="button" (click)="addItem()"> add new row</button>
<div formArrayName="instructions" *ngFor="let a of filmForm.get('instructions').controls; let i = index">
<div [formGroupName]="i" style="margin-bottom: 10px;">
<label for="name">Name:</label>
<input type="text" name="name" formControlName="instructions">
<br><br>
</div>
</div>
<div class="submit">
<button type="submit">Save</button>
</div>
</form>
</div>
TS:
registerForm: FormGroup;
submitted = false;
instructions: FormArray;
filmForm: FormGroup;
constructor(private formBuilder: FormBuilder) { }
ngOnInit() {
this.filmForm = this.formBuilder.group({
instructions: this.formBuilder.array([this.createItem()])
})
}
createItem() {
return this.formBuilder.group({
instructions: ['']
})
}
addItem() {
this.instructions = this.filmForm.get('instructions') as FormArray;
this.instructions.push(this.createItem());
}
save() {
console.log(this.filmForm.value)
}
I am sending array of object: check stackblitz console.log
I am send like
instructors = [{instructs : 'value one'} , {instructs : 'value one'}..]
But I need to sent:
instructors = ["value one" , "value two"];

There are two ways in which you go ahead with this.
1 - Using .map in save()
For the desired output, you can use the .map in save() function:
save() {
const instructions = this.filmForm.value.instructions.map(inst => inst. instruction);
console.log(instructions);
}
Desired Output will be:
["value one" , "value two"]
2 - Using a tags input control like ng-select
Your use case looks like a tags control use case for instructions.
There is a popular library #ng-select/ng-select which has a tags control.
You can see the usage of this library for your use case on this stackblitz.
Approach 1 is the easiest one to do but I would suggest you use tags control in approach 2 for good user experience.

You can try this.. i had the same issue.
Make the Form
form = new FormGroup({
instructorsArray: new FormArray([]),
})
get instructors(): FormGroup {
return FormControl('')
}
addInstructors() {
this.instructors.push(this.instructors);
}

Related

how can I do "twoDataBinding" with formControlName? similar with ng Model

I'm setting a model with form, but I have a problem to set a "MyModel" with a form
This is for the purpose of optimizing the handling of the forms
public myModel = new MyModel();
this.myForm = this.formBuilder.group({
firstName: new FormControl({
value: this.myModel.firstName,
disabled: false
}),
middleName: new FormControl({
value: this.myModel.middleName,
disabled: false
}),
lastName: new FormControl({
value: this.myModel.lastName,
disabled: false
}),
age: new FormControl({
value: this.myModel.age,
disabled: false
})
});
when I submit a "submit" with a button, that shows me the "this.myForm" with the elements that I added in the form
but it seems that I would not be establishing a connection as a "TwoDataBinding"
I also do not want to do this code since I see it very redundant
also
when it comes to many forms and even worse if you decide to change or refactor the attributes of that object
this.myModel.firstName = this.myForm.controls['firstName'].value;
this.myModel.lastName = this.myForm.controls['lastName'].value;
this.myModel.middleName = this.myForm.controls['middleName'].value;
this.myModel.age = this.myForm.controls['age'].value;
You can see the complete code here:https://stackblitz.com/edit/form-model-hammer
of a form model, if you want to make changes makes a FORK to share, thanks:
also for the purpose of avoiding this alert in the picture
If you want to use 2-way binding, you should use template-driven forms instead. It allows you to use ngModel to create two-way data bindings for reading and writing input-control values.
The principles of reactive forms follows the 'one-way' rule, whereby you follow an immutable method of managing the state of your forms, such that there is greater separation of concern between your template and component logic. You can read more about the advantages of reactive forms on the above link.
If you think reactive forms is not what you want, you should revert to using template driven forms, as stated on the first paragraph.
One thing to take note, you should not use ngModel with reactive forms, as this will defeat the purpose of immutability.
However, if you are planning to stick to using reactive forms, you can simplify your code by doing this instead:
1) Initialising and declaring your reactive forms.
this.myForm = this.formBuilder.group({
firstName: [{value: this.myModel.firstName, disabled: true}],
middleName: [this.myModel.middleName],
lastName: [this.myModel.Name],
age: [this.myModel.age],
});
2) Get reactive form data:
// since the properties of myModel and myForm FormControl names are the same
this.myModel = {...this.myForm.value};
3) Update reactive form data:
this.myForm.patchValue(this.myModel);
You should stop using ngModel with Reactive forms as it is deprecated now .
You can simplify the code like below :
this.myModel.firstName= 'FIRST NAME';
this.myForm = this.formBuilder.group({
firstName:[{
value: this.myModel ? this.myModel.firstName : '',
disabled: false
}],
middleName: [{
value: this.myModel ? this.myModel.middleName : '',
disabled: false
}],
lastName: [{
value: this.myModel ? this.myModel.lastName : '',
disabled: false
}],
age:[{
value: this.myModel ? this.myModel.age : '',
disabled: false
}]
});
Listen to (ngOnSubmit) event and write a function to save the form values .
This can be achieved in the below way :
save(myForm : any){
let form = myForm as MyModel;
console.log(form);
form.otherProperties = 'nothing';
}
Or :
save(myForm : MyModel){
let form = JSON.parse(JSON.stringify(myForm)); //for copy
console.log(form);
form.otherProperties = 'nothing';
console.log( 'added a new property', form);
}
And in your html :
<div>
<form [formGroup]="myForm" (ngSubmit)='save(myForm.value)'>
<label>
<span>
Fisrt name:
</span>
<input type="text" formControlName="firstName">
</label>
<label>
<span>
Middle name
</span>
<input type="text" formControlName="middleName">
</label>
<label>
<span>
Last name
</span>
<input type="text" formControlName="lastName">
</label>
<label>
<span> Age: </span>
<input type="number" formControlName="age">
</label>
<div style="display: block">
<button (click)="onShowModel()">
show model
</button>
</div>
<div style="display: block">
<button>
set model from form
</button>
</div>
</form>
</div>
<div>
<p class="red"> from model : </p>
<span class="red"> Model: {{myModel | json}} {{nothing}}</span>
</div>
<div>
<p class="blue"> from form, binding model : </p>
<span class="blue"> Model: {{myForm.value | json}}</span>
</div>
I have also forked your example : Example

AngularJS ng-repeat questions and init inputs with matching answer object

I am using an ng-repeat to repeat through questions provided by an ajax response and I need the ng-model of each question input to point to a separate answers array.
The question array looks like this
bookingQuestions: [
0: {
label: 'Any allergies?',
type: 'text',
id: 1234
},
1: {
label: 'Names of attendees',
type: 'text',
id: 1235
}
]
I create the answers array by looping through all the questions and pushing the id and an empty answerValue property into my empty bookingAnswers array. The answers array looks like this:
bookingAnswers: [
0: {
id: 1234,
answerValue: ''
},
1: {
id: 1235,
answerValue: ''
}
]
In the markup, I'm attempting to init the answerObj by getting the correct answer object to match the corresponding question.
<div class="question" ng-repeat="question in bookingQuestions">
<label class="question-label" for="{{question.id}}">{{question.label}}
</label>
<input type="text" name="{{question.id}}" ng-model="answerObj"
ng-init="answerObj = getAnswerObj(question)">
</div>
The JS function:
$scope.getAnswerObj = function(question) {
angular.forEach(bookingAnswers, function(answer) {
if(question.id === answer.id) {
return answer.answerValue;
}
});
}
Even though the JS function successfully returns the correct object property, the ng-model isn't being updated to use it. How do I get this working?
You bind the ng-model of all your inputs to some answerObj meaning they all point to the same variable. Using $index you can access the index of the current iteration. So you could do something like this:
<input type=“text“ name="{{question.id}}"
ng-model="bookingAnswers[$index].answerValue"> </div>
<div class="question" ng-repeat="question in bookingQuestions">
<label class="question-label" for="{{question.id}}">{{question.label}}
</label>
̶<̶i̶n̶p̶u̶t̶ ̶t̶y̶p̶e̶=̶"̶t̶e̶x̶t̶"̶ ̶n̶a̶m̶e̶=̶"̶{̶{̶q̶u̶e̶s̶t̶i̶o̶n̶.̶i̶d̶}̶}̶"̶ ̶n̶g̶-̶m̶o̶d̶e̶l̶=̶"̶a̶n̶s̶w̶e̶r̶O̶b̶j̶"̶
<input type="text" name="{{question.id}}" ng-model="answerObj.answerValue"
ng-init="answerObj = getAnswerObj(question)" />
</div>
$scope.getAnswerObj = function(question) {
angular.forEach(bookingAnswers, function(answer) {
if(question.id === answer.id) {
̶r̶e̶t̶u̶r̶n̶ ̶a̶n̶s̶w̶e̶r̶.̶a̶n̶s̶w̶e̶r̶V̶a̶l̶u̶e̶;̶
return answer;
}
});
}

Add data in List onclick event

I am trying to add items from textbox into the list and want to display on main page. Here is my code sample
HTML Code:
<div ng-controller="purchaseInvoiceInquiryController as c" ng-init="c.initializeController()">
<input type="text" ng-model="c.name" placeholder="Enter the Book" />
<input type="text" ng-model="c.price" placeholder="Enter a Price" />
<button ng-click="c.addBooks()">Add the Book</button></p>
<td ng-repeat="x in c.books"> {{ x.name + ' - ' + x.price}}</td>
and angular controller code is :
this.addBooks = function () {
c.books = [{
name: c.name,
price: c.price
}];
};
Its only add one item in that list when i try to add another item it will override the values.
Initialize books to empty array in controller and use push method of array to add new books. You may need to add logic to avoid duplicates.
this.books = [];
this.addBooks = function () {
this.books.push({
name: c.name,
price: c.price
});
};
Use push instead.
this.addBooks = function () {
c.books.push({
name: c.name,
price: c.price
});
};

Managing a Reactive Form value and the value is an object

I have an Array I'm getting from the server, which contains Objects like this:
[
{LanguageName: 'English', ID : 2},
{LanguageName: 'Dutch', ID : 1},
{LanguageName: 'portuguese', ID: 3},
]
I'm handling this by by creating a Form-Array.
My Issue:
I want that if the user changes this input, it will change only the property of the Name, something like: anyFormName.controls.value.LanguageName, and not replacing the whole value altogether to a string, so insted of end up getting :
anyFormName.controls.value = "User's Input"
, I'll get:
anyFormName.controls.value = {LanguageName: "User's Input", ID : 2}
I've worked around this issue before with setValue() to the specific control, and saving the data in another array so I can compare the position by the indexes of the form Array. seems to me there probably be a better way...
thanks a lot!
Tal, in general you'll get a formArray like
<div *ngIf="myFormArray" [formGroup]="myFormArray">
<div *ngFor="let item of myFormArray.controls; let i=index" [formGroupName]="i">
<input formControlName="ID">
<input formControlName="LanguageName">
</div>
</div>
{{myFormArray?.value|json}}
//Or
<div *ngIf="myForm" [formGroup]="myForm">
<div formArrayName="data">
<div *ngFor="let item of myForm.get('data').controls; let i=index" [formGroupName]="i">
<input formControlName="ID">
<input formControlName="LanguageName">
</div>
</div>
</div>
{{myForm?.value|json}}
where you has some like
myForm:FormGroup
myFormArray:FormArray;
values=[
{LanguageName: 'English', ID : 2},
{LanguageName: 'Dutch', ID : 1},
{LanguageName: 'portuguese', ID: 3},
]
ngOnInit() {
this.myForm=this.fb.group({
data:this.fb.array(this.createFormArray(this.values))
})
this.myFormArray=this.fb.array(this.createFormArray(this.values));
}
createFormArray(values:any):FormGroup[]
{
return values.map(x=>{
return this.fb.group(
{
LanguageName:x.LanguageName,
ID:x.ID
}
)
})
}
Just not include the input formControlName="ID"
As long as I understand you properly, you're trying to change the form control name instead of its value. That can be accomplished by this method:
changeFormFieldName(oldField: string, newField: string): void {
var newControls: {[key: string]: FormControl} = {};
Object.keys(this.form.controls).map((field: string) => {
if (field==oldField) {
newControls[newField] = this.form.controls[field];
} else {
newControls[field] = this.form.controls[field];
}
});
this.form = new FormGroup(newControls);
}
assuming your form group object is under this.form.

How to get an input field value in Vue

I'm new to Vue and I would like some help getting a value from an input field:
In my form I have:
<input type="hidden" id="groupId" value="1">
If I was using jQuery I would do:
var group_id = $('#groupId').val();
However, in Vue I don't know how to bind the hidden field:
<div id="app">
<input type="text" v-model="groupId"> //Where do I put the value?
</div>
new Vue({
el: '#app',
data: {
groupId: //What do I put here to get the field's value?
}
How can I achieve this?
Update to the update: See this answer. Previously updated answer was wrong.
Original answer:
In Vue, you don't get things from the view and put things into the view. Vue does that. You do all manipulations in the viewmodel, and make bindings in the view so that Vue knows how to synchronize it. So you'd bind the input to your model data item:
<input type="hidden" id="groupId" v-model="groupId">
and set its value in your viewmodel:
data: {
groupId: 1
}
I had the same question. I'm working with Vue + Laravel.
For me, the solution was simple after searching and not finding a concrete solution in the Vue documentation.
Simply:
document.getElementById('MyId').value;
Details in → https://www.w3schools.com/jsref/prop_text_value.asp
It is not the most efficient solution, but it works for now!
Greetings.
Working sample of getting value from input field in this case it is hidden type:
<input type="hidden" name="test">
<script>
new Vue ({
created () {
const field = document.querySelector("input[name=test]").value
console.log(field)
}
})
</script>
this code helped me
i hope that this work with you
define the input
<div class="root">
<input type="hidden" ref="groupId" value="1">
<button type="button" v-on:click="get_id()">test</button>
</div>
define the method
new Vue({
el: ".root",
data: {
id: null,
}
methods: {
get_id() {
this.id = this.$refs.groupId.value;
}
}
});
// if you want it displayed on your page, use {{ groupId }}
/* you can get the value by using #change.enter=".." #keypress.enter="getInputValue",
or #input="getInputValue" or #click="getInputValue" using button,
or if it is with a form element, #submit.prevent="getInputValue" */
/* #keypress.enter tracks input but only calls the function when the Enter key
is pressed, #input track changes as it's being entered */
// it is important to use event.preventDefault() when using #change or #keypress
<div id="app">
<input type="text" v-model="groupId">
<p> {{ groupId }} </p>
<button #click="getInputValue">Get Input</button>
</div>
new Vue({
el: '#app',
data: {
groupId: //What do I put here to get the field's value?
// for what to put there, you can use an empty string or null
groupId: "",
},
// to get the value from input field
methods: {
getInputValue: function() {
if(this.groupId !== "") {
console.log(this.groupId);
}
},
}
})
look at this I did it in laravel, vuejs, vuetable2 and children's row, and don't use the v-model:
this.$refs['est_'+id_det].localValue
en VUE:
<div class="col-md-3">
<b-form-select class="form-control selectpicker" :ref="'est_'+props.row.id_detalle_oc"
:value="props.row.id_est_ven" v-on:change="save_estado(props.row.id_detalle_oc)">
<option value="0">Sin estado</option>
<option value="1">Pendiente</option>
<option value="2">Impresa</option>
<option value="3">Lista</option>
</b-form-select>
in methods
methods: {
save_estado:function (id_det){
var url= 'ordenes-compra/guardar_est_ven'
var id_estado = this.$refs['est_'+id_det].localValue
axios.post(url,{
id_det: id_det,
id_est_ven: id_estado,
est_ven: est_ve
}).then(function (response) {
var respuesta= response.data;
if(respuesta == "OK"){
swal({
type: 'success',
title: '¡Éxito!',
text: 'Estado modificado',
confirmButtonText: 'Entendido',
})
}
})
.catch(function (error) {
console.log(error);
});
},
I hope it helps, I've been hanging around for a while.
Regards
Hi you can also try the following:
const input = this.$el.firstElementChild;
in case you are using TypeScript, declare input as:
: HTMLInputElement
Then, you can simply get the value if you do:
input.value
Hope it helps!
Ok, this does the job: document.querySelector('#groupId').getAttribute('value');

Categories