Selected option is undefined - Angular material - angular-material

I want to know from a list which options the user selected.
In both ways the event/the object is undefined.
What is the best way to do it?
My first way:
<mat-form-field>
<mat-select [(value)]="selectedUserType" multiple (selectionChange)="filterByCustomFields()">
<mat-option *ngFor="let custom of filteredRows" [value]="custom.value">
{{custom.fieldHebKey}}
</mat-option>
</mat-select>
</mat-form-field>
And the second:
<mat-select [formControlName]="'customField'" multiple (selectionChange)="filterByCustomFields($event)">
<mat-option *ngFor="let custom of filteredRows" [value]="custom.value">
{{custom.fieldHebKey}}
</mat-option>
</mat-select>
</mat-form-field>

Using reactive forms the second option is usually a better way.
Make sure you have assigned the filteredRows with the fieldHebKey and value property, if the value property is missing you might get a null or undefined value.
And instead of using selectionChange you can listen to value changes event of the form control in ngOnInit
filteredRows = [
{fieldHebKey: 1, value: 'one'},
{fieldHebKey: 2, value: 'two'},
{fieldHebKey: 3, value: 'three'}
]
ngOnInit(){
this.formGroup.get('customField').valueChanges.subscribe(val => {
console.log(val)
})
}

Related

How to trigger manually mat-checkbox change event

I have hidden mat-checkbox which is binded to formControl and I need to trigger this formControl change while clicking on some icon (which is supposed to be binded to checkbox). But I can't figure out how to trigger manually that change event. Unfortunatelly .toggle() method of mat-chechbox doesn't change my formControl value and doesn't trigger change event
<mat-checkbox [hidden] #availabilityCheckbox (change)="toggleInputs(i)" formControlName="available"></mat-checkbox>
<mat-icon
(click)="availabilityCheckbox.toggle()"
class="variants-action-icon m-r-1"
>
{{ variationsFormArray.controls[i].get('available').value ? 'visibility' : 'visibility_off' }}
</mat-icon>
In your case please try out this,
<mat-icon
(click)="availabilityCheckbox._onInputClick($event)"
class="variants-action-icon m-r-1"
>
{{ variationsFormArray.controls[i].get('available').value ? 'visibility' : 'visibility_off' }}
</mat-icon>
Actually _onInputClick($event) is the event we need to call on checkbox template reference. It will trigger the (change) event.
if you use reactive form, use it
variationsFormArray.controls[i]?.get('available')?.setValue(!variationsFormArray.controls[i]?.get('available')?.value);
it would be better to extract this in a function it your ts

Svelte input binding breaks when a reactive value is a reference type?

(I'm new to Svelte so it is quite likely that I'm doing something wrong here)
UPDATE: I've added a second, slightly different REPL which may demonstrate the problem better. Try this one: https://svelte.dev/repl/ad7a65894f8440ad9081102946472544?version=3.20.1
I've encountered a problem attempting to bind a text input to a reactive value.
I'm struggling to describe the problem in words, so hopefully a reduced demo of the issue in the attached REPL will make more sense.
https://svelte.dev/repl/6c8068ed4cc048919f71d87f9d020696?version=3.20.1
The demo contains two custom <Selector> components on a page.
The first component is passed two string values ("one" and "two"):
<Selector valueOne="one" valueTwo="two"/>
Clicking the buttons next to the input field sets selectedValue to one of these values.
This, in turn, triggers the following reactive declaration to update:
$: value = selectedValue
The input field is bound to this reactive value:
<input type="text" bind:value>
So clicking the "One" button sets the input text to "one", and clicking the "Two" button sets the input field to "two".
Importantly though, you can still type anything into the input field.
The second component is passed two array values:
<Selector valueOne={[1, "one"]} valueTwo={[2, "two"]}/>
Again, clicking the buttons sets selectedValue to one of these.
However this time the reactive declaration depends on an array element:
$: value = selectedValue[1]
Everything works as before, except now you can no longer type into the input field at all.
So the question is - why does <input bind:value> behave differently for these two:
$: value = aString
vs
$: value = anArray[x]
It seems that this is only an issue when using two-way bindings.
By switching to a one-way and an on:input handler, the problem goes away:
i.e. instead of this:
<input type="text" bind:value={valX}/>
use this:
<input type="text" value={valX} on:input={e => valX = e.target.value}/>
I'm pretty sure your reactive declaration is overwriting your bound value as soon as it changes, which is with every key stroke on the input and every button press. Meaning it technically is working, you're just reverting it each time it changes. Check out this version of it that uses a watcher.
Also binding to a reactive declaration means you're never actually changing the variables with the input (which you can see in your JSON result on the first selector when you type in the input the value doesn't update only on button click).
Why not lose the reactive declaration and bind directly to the variable you want. Then use an {#if} block to switch between which version of the input you're showing based on the truthiness of index?
<script>
export let valueOne;
export let valueTwo;
export let index;
let selectedValue = index? [] : '';
let selectValue = (val) => selectedValue = val;
</script>
{#if index}
<input type="text" bind:value={selectedValue[index]} placeholder="Type anything...">
{:else}
<input type="text" bind:value={selectedValue} placeholder="Type anything...">
{/if}
<button on:click={() => selectValue(valueOne)}>One</button>
<button on:click={() => selectValue(valueTwo)}>Two</button>
<p>
<strong>Selected value:</strong> {JSON.stringify(selectedValue)}
</p>
By binding directly to the selectedValue or an index of it you have the added benefit of changing the value with the input. Here's a working example in the REPL

Change disabled attribute value for matInput

I have an issue related to the existing question
Cannot disable matInput element with this
Suggested answer works just fine:
ngOnInit() {
this.form = this.fb.group({
name: new FormControl({ value: '', disabled: this.disabled })
});
But when I change this.disabled value to true - disabled attribute isn't changed. Is there a way to change the disabled attribute for matInput?
You can't use that form, because when you create a FormControl you are passing that value, in your case the value of this.disabled. You are not binding properties, you are only passing a value to make some checks, this value is not reflecting input properties' changes.
You can't achieve your goal by this way, you need to enable and disable your input manually, like this:
let control = this.form.get('name')
control.disabled ? control.enable() : control.disable();
Obviously you can put it into a click event directly into your template, something like this:
<button (click)="this.form.get('name').enable()">Enable</button>

Using Mat Option Group in Reactive Forms

I am trying to implement a radio button group in a form. This is how I did it:
.ts
yesNo: any = [
'Yes',
'No'
];
createForm() {
this.createPropertyForm = this.fb.group({
latepymtpen: [null],
});
ngOnInit() {
this.createForm();
}
.html
<mat-form-field class="occupy-half-wmargin">
<mat-radio-group formControlName="latepymtpen">
<mat-radio-button *ngFor="let yn of yesNo" [value]="yn">
{{yn}}
</mat-radio-button>
</mat-radio-group>
</mat-form-field>
When I run it, I get this error:
ERROR Error: mat-form-field must contain a MatFormFieldControl.
Can you please tell me what I'm doing wrong? Thank you.
MatFormField is for components like MatInput, MatSelect, and others which implement the MatFormFieldControl interface. MatRadioGroup is not one of them. In other words, you can't use a MatRadioGroup inside a MatFormField the way you have.

Why is typeahead-focus-first="scopeVariable" is not updating uib-typeahead?

I have used the uib-typeahead directive as follows :
<input type="text" id="search-box" class="form-control" data-ng-model="searchBar.search.searchString"
typeahead-on-select="searchBar.gotoPartDetails($item, $model, $label, $event)" uib-typeahead="result as result.partNumber+' '+result.lineDesc+' '+result.partDesc for result in searchBar.textTyped($viewValue)"
placeholder="Search by part number, product type, product line, keyword" typeahead-focus-first="searchBar.search.firstSelect" typeahead-popup-template-url="app/components/header/search-bar/typeahead-popup.html" typeahead-template-url="{{searchBar.search.typeaheadTemplate}}"
data-ng-focus="searchBar.focus()" data-ng-blur="searchBar.blur()">
I am basically using the "searchBar.search.firstSelect" scope variable to enable or disable first select. On controller load searchBar.search.firstSelect is set to false and based on the size of the length data displayed. If the typeahead is showing just one data in the options I am setting searchBar.search.firstSelect to true. But this is not reflecting in the UI. What do I do?

Resources