How to dynamically set the default value in Reactive form? - javascript

I am creating the table with the looping, and if the loop value matches with the particular character I want to set the Reactive Form default value of Repeat else I want to set the empty value in the Reactive Form. Following Is my code
typescript
rDefault:string = "";
create(){
let form = this.fb.group({
rp:[this.rDefault]});
return form;
}
template
<tbody *ngFor="let c of ch.vl; let i = index" [formGroupName]="i">
<tr class="ui-widget-content ui-datatable">
<td>
{{rpm[ofs+i].label}}
</td>
<td>
<p-dropdown formControlName="rp" [options]="rpm[ofs+i].label =='REPEAT'? compOpt : []" appendTo="body" [disabled]='rpm[ofs+i].label == "REPEAT"?false:true'></p-dropdown>
</td>
</tr>
</tbody>
If {{rpm[ofs+i].label}} this value is equal to "Repeat" I want to set the default form values as "Repeat", else empty value. How can I achieve this?

Got the solution for my question but I don't know this is the correct way or not?
In the every loop I am calling the another method from [option] and setting the value in that method.
template file
<td>
<p-dropdown formControlName="rp" [options]="changeDefault(rpm[ofs+i].label)" appendTo="body" [disabled]='rpm[ofs+i].label == "REPEAT"?false:true'></p-dropdown>
</td>
Updated TS file
rDefault:string = "";
//this method will change value of rDefault
changeDefault(val){
this.rDefault = val == "REPEAT" ? "REPEAT" : "";
let rtnar = 'REPEAT'? this.compOpt : [];
return rtnar;
}
//
create(){
let form = this.fb.group({
rp:[this.rDefault]});
return form;
}

Related

I an trying to disable and enable checkbox based on value in angular 8

Here is my code
I am having List Array like: this is getCall.
ktsessions =
[ {"presenter":"Bharath","topic":"Angular","status":"scheduled","emailId":"bharathkumar#gmail.com"}, {"presenter":"Sayyad","topic":"Angular","status":"organized","emailId":"raheemsayyad#gmail.com"},{"presenter":"Kanchan","topic":"APS","status":"scheduled","emailId":"kanchanubey#gmail.com"} ];
<tr *ngFor = "let ktsession of ktsessions >
<td ><input type="checkbox" [disabled]='disabled'></td>
</tr>
TS code:
getktsession(){
this.service.getKtsession().subscribe(data =>{
console.log('get', data);
this.ktsessions = data;
this.ktsessions.find(user => {
if(user.presenter ==="Kanchan"){
this.disabled = true
} else {
this.disabled = false;
}
});
});
}
There are several issues here.
<tr *ngFor = "let ktsession of ktsessions > - Missing closing quote after ktsessions
<td ><input type="checkbox" [disabled]='disabled'></td> - [disabled]='disabled' should be [disabled]="ktsession.disabled". Each checkbox instance needs to have its own disabled property. [disabled]='disabled' sets each checkbox's disabled property to the disabled property of the component class instance rather than the checkbox instance.
this.ktsessions.find(user => { - Array#find is not an appropriate method to use here, even though it happens to work since you're not returning anything from the callback function and it will therefore iterate the entire array. Array#find is for searching an array for an element that matches the specified criteria and returning that element, not for iterating over an array and setting properties on each element, which is what you're doing here. Array#forEach is the appropriate method for that.
this.disabled = true and this.disabled = false - these are setting the disabled property on the component class instance (which is what this refers to), but what you need to do is set the disabled property on each user instance: user.disabled = true or user.disabled = false.
So your template should look something like this:
<tr *ngFor="let ktsession of ktsessions">
<td>
<input type="checkbox" [disabled]="ktsession.disabled" /> <!-- reference "ktsession.disabled" instead of "disabled" -->
{{ ktsession.presenter }}
</td>
</tr>
And your subscribe should look something like this:
this.getKtsession().subscribe((data) => {
this.ktsessions = data;
this.ktsessions.forEach((user) => { // <-- use forEach, not find
if (user.presenter === 'Kanchan') {
user.disabled = true; // <------------ set user.disabled, not this.disabled
} else {
user.disabled = false; // <----------- set user.disabled, not this.disabled
}
});
});
Here's a StackBlitz showing it working with those changes.

React web app- unique inputs from a table of variable lengths

I am building an app to help me learn react and solidity. I have a table which lists available products on the site. I want customers to be able to input the number of items they would like to buy for each product (each row) separately.
It works if I make all of them change a single variable in my state but stylistically I would like each row to have a unique value. To solve this I created an array to hold each value ( the array is called inputs). The tough part here is that the number of products (rows in the table) can vary so I cant just hard code it.
Rendering the table:
<tbody className="has-text-black-bis">
{indices.map((a) => (
<tr className="rows">
<td ><strong>{this.state.itemNames[a]}</strong></td>
<td ><strong>{this.state.costs[a]} Wei</strong></td>
<td ><strong>{this.state.quantities[a]}</strong></td>
//This row! <td >
Qty: <input type="number" className='table-input' name="inputs" value={this.state.inputs[a]} onChange={()=>this.handleTableInput(a)} />
<button type="button" className='buy-btn' onClick={()=>this.buyItem(a)}> Buy!</button>
</td>
</tr>
))}
</tbody>
Handling the input changes normally -This did not work when passing this.state.inputs[a] as the value as other rows would change as well:
handleInputChange = (event) => {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
I thought to change the above function to something like this where a (my index) is passed into the function. The problem is that I am not sure how to access the 'event' types like in the above generic function and thus not sure how to access the value that the user has input.
handleTableInput = (ind) => {
const {inputs} = this.state;
inputs[ind] = "value from table input";
this.setState({inputs: inputs})
}
Thank you for any help!

Angular - How can I access Template variable/reference from typescript?

In my Angular project I am trying to access the value present in <td [innerHTML]='rupee.replaceHTML' #term></td> and assign it to vaiable newdata.
More on the functionality here, I have 2 buttons change and concourse. The value present in below HTML will change when I press concourse button. I was to save that changed value in variable newdata using localStorage so that I can access it later.
How can I access that html value and store it in new_data?
.html file
<mat-list-item>New Life</mat-list-item>
<mat-list class="textFields">
<table>
<tr>
<td [innerHTML]='rupee.replaceHTML' #term></td> ---> Access whatever value is here
</tr>
</table>
</mat-list>
//button
<button mat-raised-button type='button' (click)='concourse(kada, term)'>Confirm
component.ts
export class Pinky {
#ViewChild('term') editElem!: ElementRef<HTMLTableDataCellElement>;
//button function
concourse(rec: FillData, nada: HTMLTableDataCellElement) {
const { a,b,c,d } = rec;
let maan= nada.innerText;
localStorage.setItem('FillData', JSON.stringify(rec));
var new_data = JSON.parse(localStorage.getItem('FillData') || '{}') as FillData
-------------------//Can I access #term value here?-------------------------
new_data.{{?}}= maan; ----------> Assign the value here ?
localStorage.setItem('FillData', JSON.stringify(new_data));
}
Interface
export interface DraneMan {
maan:string;
}
You already have a #ViewChild('term')
so you can just get it from this.editElem.innerHTML.
What's more, you have a binding [innerHTML]='rupee.replaceHTML', so, reading from the DOM something that is bound seems like the wrong data flow.
I would just use ruppee.replaceHTML as source of truth.

Vue v-text-field - previous value is automatically displayed when clicked

The Vue input fields (v-text-field) automatically show the previous input when I click on the text field.
Actually, I delete the value from all inputs with the blue button (which also creates additional random tables). The reset works, but why is the value displayed again?
What I tried: I used v-form to delete the value of all inputs with this.$refs.form.reset(); (see https://vuetifyjs.com/en/components/forms/#misc). That didn't solve the problem.
This is how it looks:
GIF
HTML
<v-simple-table>
<template v-slot:default>
...
<tbody>
<tr :class="verb.ich">
<td>
<v-text-field label="ich"></v-text-field>
</td>
</tr>
<tr :class="verb.du">
<td>
<v-text-field label="du"></v-text-field>
</td>
</tr>
<tr :class="verb.er">
<td>
<v-text-field label="er/sie/es"></v-text-field>
</td>
</tr>
...
...
</tbody>
</template>
</v-simple-table>
...
<v-btn #click="next"> Weiter </v-btn>
Method next():
next: function () {
var allInputs = document.getElementsByTagName("input");
for (var i = 0, max = allInputs.length; i < max; i++) {
allInputs[i].value = "";
allInputs[i].style.backgroundColor = "white";
}
...
}
Solution
(with the help of Michael LevĂ˝'s answer)
v-model
<td>
<v-text-field v-model="verb.val[0]"></v-text-field>
</td>
...
reset value
for (var i = 0; i < this.verben.length; i++) {
this.verben[i].val[0] = "";
...
}
in each array
verben: [
{
val: ["", "", "", "", "", ""],
...
}
v-text-field has some internal variable which saves the value when you are typing. Your next() method doesn't clear this value but only sets value of the rendered <input> control - when you click on the control, v-text-field is re-rendered and shows the value stored inside
Your next method is an example how not to work with form items in Vue. Vue is data driven. For each control you need a variable in data() section of your component and use v-model to bind the control to that variable.
Now when you want to change the value programmatically, you change the data in your component (not in the DOM)
Form Input Bindings
Vuetify form controls works same way - examples

How to validate duplicate entry in angular form builder array?

I am using angular6 reactive form with form builder and form array. I am facing problem with duplicate subject entry from drop down in form array. How to validate to avoid duplicate entry in from array.
I have a subject list with drop down. When i click on add button then a subject array will add. If i add similar subject it also be added. But i want to avoid duplicate subject entry. When i entry duplicate subject then a validation message will show and save button will disable.
stackblitz
ts code
olevelSubForm = this.fb.group({
olevelSubArray: this.fb.array([
])
});
olevelSubjectList: any = [ 'Geography','Mathematics',
'Physics','Chemistry'];
constructor(private fb: FormBuilder) {}
ngOnInit() {
this.addItemOlevel();
}
// olevel
createOlevelSub(): FormGroup {
return this.fb.group( {
olevelSubject: new FormControl('', Validators.compose(
[
Validators.required
]
)),
});
}
addItemOlevel() {
const control = <FormArray>this.olevelSubForm.controls.olevelSubArray;
control.push(this.createOlevelSub());
}
saveData() {
console.log('saved')
}
html code
<form [formGroup]="olevelSubForm" >
<div formArrayName="olevelSubArray">
<table>
<thead>
<tr style="font-size: 15px;">
<th>Subject</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of olevelSubForm.get('olevelSubArray').controls; let i = index;" [formGroupName]="i">
<td>
<select formControlName="olevelSubject">
<option *ngFor="let olevelSub of olevelSubjectList" [value]="olevelSub">{{ olevelSub }}</option>
</select>
</td>
<td>
<button style="float: right" [disabled]="olevelSubForm.invalid"(click)="addItemOlevel()"> Add
</button>
</td>
</tr>
</tbody>
</table>
<button [disabled]="olevelSubForm.invalid"(click)=saveData()>Save</button>
<pre> {{ olevelSubForm.value | json }} </pre>
</div>
In my comment I put and answer with a different aproach: that the options you can select was different in each level, so you can not choose some yet choosed. that, if you has a function like
getSubjectForFormArray(i, olevelSubjectList) {
return i == 0 ? olevelSubjectList :
this.getSubjectForFormArray(i - 1, olevelSubjectList.filter(x =>
x != this.olevelSubForm.get('olevelSubArray').value[i-1].olevelSubject))
}
Yes is a recursive function that begins with all the options and in each step, remove from the list the value we are choose. So, your option list can be like
<option *ngFor="let olevelSub of getSubjectForFormArray(i, olevelSubjectList)"
[value]="olevelSub">{{ olevelSub }}</option>
Anyway, this dont' avoid that if, e.g we choose "Mathematics","Chemistry", if change the first combo to Chemistry, we'll get two "Chemistry". So, we are going to check each change of the array. That's in ngOnInit
this.olevelSubForm.get('olevelSubArray').valueChanges.subscribe(res=>{
res.forEach((x,index)=>{
//res is the value of the array,e.g. -in one moment-
//[{olevelSubject:'Mathematics'},{olevelSubject:'Chemistry'},{olevelSubject:null}]
if (index)
{
//before becomes an array with the values selected before, eg. -in one moment-
// ['Mathematics','Chemistry']
const before=res.slice(0,index).map(x=>x.olevelSubject)
if (before.find(x=>x==res[index].olevelSubject))
{
(this.olevelSubForm.get('olevelSubArray') as FormArray)
.at(index).setValue({olevelSubject:null})
}
}
})
})
See the stackblitz

Categories

Resources