How to enable Item on click in Angular - html

I have a list of subsections in my dialog container. I'm trying make all of them disabled when the dialog is open and only enabled selected subsection when the pencil icon is click for that subsection.
For example....
when user click subsection 1 pencil icon
Subsection 1 enabled
Subsection 2 disabled
Subsection 3 disabled. ....
and process will be the same for subsection 2 and 3. Any suggestion or help will be really appreciated.
<p class="substyle">Subsections</p>
<div class="substyle" *ngFor="let subsection of section.subSections">
<mat-form-field appearance="fill">
<input matInput(ngModelChange)="nameChanged({newValue: $event,
isSection: false, id: subsection.id}
[(ngModel)]="subsection.sectionName">
</mat-form-field>
<button mat-icon-button color="primary"
(click)="editDoc(subsection)"> <mat-icon>edit</mat-icon>
</button>
<button mat-icon-button (click)="openConfirmDialog(subsection, false)"
*ngIf="isSubsection"><mat-icon>delete</mat-icon>
</button>
TS
// THis is called when pencil icon is click
editDoc(value) {
this.subsectionToEdit = value;
this.refreshEditor = false;
}
// Delete Subsections
this.HelpService.deleteHelpSubsection(sec.id).subscribe(() => {
const index = this.mappedSections.findIndex((value) => value.id == sec.parentId);
if (~index) {
this.mappedSections[index].subSections = this.mappedSections[index].subSections.filter((subsection) => subsection.id != sec.id)
}
})

You can try something like this
In the input bind the [disabled] attribute to a boolean, like I have below:
<p class="substyle">Subsections</p>
<div class="substyle" *ngFor="let subsection of section.subSections">
<mat-form-field appearance="fill">
<input [disabled] = "subsection.id !== selectedId" matInput style="width: 200px; height: 15px;" type="text"
(ngModelChange)="nameChanged({newValue: $event, isSection: false, id: subsection.id})"
[(ngModel)]="subsection.sectionName">
</mat-form-field>
<button mat-icon-button color="primary" matTooltip="Edit documents for this Subsection"
style="bottom: 10px;" (click)="editDoc(subsection)"> <mat-icon>edit</mat-icon>
</button>
<button mat-icon-button color="primary" matTooltip="Delete this
Subsection" (click)="openConfirmDialog(subsection, false)"
style="bottom: 10px;" *ngIf="isSubsection"><mat-icon>delete</mat-icon>
</button>
Then in your editDoc function, do the following:
editDoc(value) {
// make sure you make selectedId a property before doing this
this.selectedId = value.id // set the selectedId property to the selected value id
this.subsectionToEdit = value;
this.refreshEditor = false;
}
So what will happen is, whenever the selectedId is set, it will set all the inputs that don't belong to the selected subsection to disable automatically.

Related

How can I perform click events in a select dropdown (Angular)?

I have two buttons (month, year) that react to different events... Now I would like to insert these events in a select. Can you please tell me how this works?
My Code:
// Solution with buttons
<button class="menu-button" type="button" mat-raised-button [ngClass]="{'active': selectedMenuLeft === 'monthButton'}" (click)="activateButton(1)">Monat</button>
<button class="menu-button" type="button" mat-raised-button [ngClass]="{'active': selectedMenuLeft === 'yearButton'}" (click)="activateButton(2)">Jahr</button>
activateButton(check) {
if (check === 1) {
this.selectedMenuLeft = 'monthButton';
this.navService.sendNavEventUpdate('month');
} else {
this.selectedMenuLeft = 'yearButton';
this.navService.sendNavEventUpdate('year');
}
}
// The same with a select. What do I have to optimize?
<select class="upload_slc" required title="">
<!-- Options -->
<option value="content" *ngFor="let navValue of menuLeftMobile" [value]="navValue">
{{ navValue }}
</option>
</select>
// Menu left in mobile
menuLeftMobile: Array<string> = ['Monat', 'Jahr'];
<mat-select placeholder="Select Menu" name="nav_value"
(selectionChange)="menuChangeAction(nav_value)"
[(ngModel)]="nav_value">
<mat-option *ngFor="let navValue of menuLeftMobile"
[value]="navValue">{{ zone.label }}</mat-option>
</mat-select>
In your component you can do the following:
nav_value: any;
menuChangeAction(value) {
console.log(value) // you will get your selected value here
}
The Simplest Way To That Is
<select #mySelect (change)='onOptionsSelected(mySelect.value)'>
And Function Will Be Like This
activateButton(check) {
if (check === "Monat") {
this.selectedMenuLeft = 'monthButton';
this.navService.sendNavEventUpdate('month');
} else {
this.selectedMenuLeft = 'yearButton';
this.navService.sendNavEventUpdate('year');
}
}
Hope This Will Work For You
You could do it by two-way binding to ngModel directive.
Controller
menuLeftMobile: Array<string> = ['Monat', 'Jahr'];
selected: string;
onChange() {
if (selected === 'Monat') {
this.selectedMenuLeft = 'monthButton';
this.navService.sendNavEventUpdate('month');
} else {
this.selectedMenuLeft = 'yearButton';
this.navService.sendNavEventUpdate('year');
}
}
Template
<select class="upload_slc" required title="" [(ngModel)]="selected" (change)="onChange()">
<!-- Options -->
<option value="content" *ngFor="let navValue of menuLeftMobile" [value]="navValue">
{{ navValue }}
</option>
</select>
Now you don't need the additional variables selectedMenuLeft to set the class. You could use the selected in the template.
<div [ngClass]="{'active': selected === 'Monat'}"></div>

Angular Load new Autocomplete values on each select change event

I have several most important fields in my form. In first form, user should choose the company by mat-select-search. After that, by using (selectionChange) I'm calling API with selected value in the first field( this is company id) and return users from that company to autocomplete for recipient fields. It works perfectly, if user does not change his chosen company. But if he do that (selectionChange) method doesn't reload autocomplete with new value. There is a situation in which the user has another company selected, and autocomplete remains from the previous one. Event only loads new one if the previous output was empty.
Is it possible to change this behavior? May be it,s possible to delete previous results from api calling?
My form :
<form [formGroup]="orderForm" novalidate (ngSubmit)="createOrder()">
<div class="row">
<div class="col-md-12">
<mat-form-field class="example-full-width" formGroupName='Company'>
<mat-select ngDefaultControl placeholder="Company" #singleSelect formControlName="id" (openedChange)="onSelectionChange($event)" [(value)]="selectedVariable">
<mat-option>
<ngx-mat-select-search [formControl]="companySelectFilter" [searching]="searching" placeholderLabel="Find company..." noEntriesFoundLabel="'no matching companies found'" ></ngx-mat-select-search>
</mat-option>
<mat-option *ngFor="let company of filteredCompanies | async" [value]="company.id">
{{company.company_name| titlecase}} {{company.company_address| titlecase}}
</mat-option>
</mat-select>
<mat-error *ngIf="orderForm.hasError('notSame')">
Recipient has another company! Select again.
</mat-error>
</mat-form-field>
</div>
</div>
<div class="row" matAutocompleteOrigin #origin="matAutocompleteOrigin">
<div class="col-md-6">
<mat-form-field class="example-full-width" formGroupName='recipient' >
<input type="text"
matInput
formControlName="user_name"
placeholder="First Name"
[matAutocomplete]="auto"
[matAutocompleteConnectedTo]="origin">
<mat-autocomplete #auto="matAutocomplete" (optionSelected)="setFormData($event)">
<mat-option *ngFor="let recipient of filteredOptions | async" [value]="recipient">
<div style="display:flex;flex-wrap: nowrap;align-items:center;justify-content:center;margin: auto;">
<span style="flex-grow: 1;flex: 1 1 33%;"> {{recipient.user_name.toString() | titlecase}} {{recipient.user_surname.toString() | titlecase}} {{recipient.company.company_name.toString() | titlecase}}
</span>
</div>
</mat-option>
</mat-autocomplete>
</mat-form-field>
</div>
<div class="col-md-6" >
<mat-form-field class="example-full-width" formGroupName='recipient'>
<input matInput formControlName="user_surname" placeholder="Last Name"[matAutocomplete]="auto"
[matAutocompleteConnectedTo]="origin" >
<mat-error *ngIf="orderForm.get('recipient.user_surname').hasError('required')">
Last Name is <strong>required</strong>
</mat-error>
</mat-form-field>
</div>
</div>
<div class="col-md-6" >
<mat-form-field class="example-full-width" formGroupName='recipient'>
<input matInput placeholder="Mobile Phone" type="text" formControlName="user_telephone" >
</mat-form-field>
</div>
OnSelected change method:
onSelectionChange(opened: boolean) {
console.log(`opened is : ${opened}`);
if (!opened && this.selectedVariable) {
this.orderForm.get('recipient.user_name').reset()
this.orderForm.get('recipient.user_surname').reset()
this.orderForm.get('recipient.user_telephone').reset()
this.filteredOptions = this.orderForm
.get('recipient.user_name')
.valueChanges.pipe(
startWith(""),
debounceTime(400),
distinctUntilChanged(),
switchMap((val) => {
return this.doFilter(this.selectedVariable, val || '');
})
);
}
}
And doFilter method :
doFilter(id: number, val: any): Observable<any[]> {
return this.recipientService.getRecipientsByCompany(id).pipe(
map((response) =>
response.filter((option) => {
return (
option.user_name
.toString()
.toLowerCase()
.indexOf(val.toString().toLowerCase()) === 0 ||
option.user_surname
.toString()
.toLowerCase()
.indexOf(val.toString().toLowerCase()) === 0
);
})
)
);
}
Finally, I found a solution. My mistake was I trying to retrieve the data from API after page loaded. Now, I load all the recipients in NgOnInit method and filter the data after user change the company.
LoadRecipients method which we put into ngOnInit:
this.recipientService
.getRecipientsObs()
.subscribe((recipients) => (this.recipients = recipients));
}
And new OnChange method :
selectedVariable: any;
onSelectionChange(opened: boolean) {
console.log(`opened is : ${opened}`);
console.log(this.selectedVariable)
if (!opened && this.selectedVariable) {
this.orderForm.get("recipient.user_name").reset();
this.orderForm.get("recipient.user_surname").reset();
this.orderForm.get("recipient.user_telephone").reset();
const formsInput = merge(
this.orderForm.get('recipient.user_name').valueChanges,
this.orderForm.get('recipient.user_surname').valueChanges
);
formsInput.pipe(
startWith(""),
debounceTime(400),
distinctUntilChanged(),
map((search) => {
if (!this.recipients) {
return [];
} else {
search = search.toLowerCase();
}
return this.recipients.filter(
(recipient) =>
recipient.company.id === this.selectedVariable &&
recipient.user_name.toLowerCase().indexOf(search) > -1 &&
recipient.user_surname.toLowerCase().indexOf(search) > -1
);
}),
delay(500)
)
.subscribe(
(filteredRecipients) => {
this.searching = false;
this.filteredRecipients.next(filteredRecipients);
},
(error) => {
this.searching = false;
}
);
}
}

How to implement a Angular 2+ step progress bar

I want to implement a 7 step progress bar in Angular2+ TypeScript+SCSS+HTML like shown in above image. I don't know how to proceed.
I have 7 steps(created, assigned, inprogress and so on) and three different paths (all 7 steps, blocked after 3 steps, rejected at initial step)
My thoughts:
Draw a line, add icons and then change icons once step is completed. should I use routing here?
add image/icons then add lines in between?
add default line, then add icons/images over it and colour the completed steps?
I am doing for a website so the words below the icons/images should resize accordingly and should work for phone size although not required at this point of time. Angular stepper has buttons and a bit complex for me. I am implementing in already existing website with internal calls for status variable. It will be placed in top right corner of the website.
Also it is ok to grey out 2 previous steps of current steps and showing next step in grey.
It's been quite confusing how to go about it, I am a very new to Angular2+.
I did something somewhat similar awhile back, but ended up scrapping it so it is not super clean. I also was just writing the name of the statuses and coloring them differently instead of having icons with labels underneath. Mine would switch to a vertical view on small screen sizes. Not sure if it will help much, but here's the html:
<div
*ngIf="appeal && statuses && statuses.length > 0 && childVisible"
fxLayout="row"
fxLayoutAlign="start center"
fxLayout.lt-md="column"
class="py-24"
>
<ng-container *ngFor="let status of statuses; let last = last; let index = index">
<span [ngClass]="{ 'green-fg': index <= selection, 'orange-fg text-bold': index === selection }">{{
status.statusDescription
}}</span>
<mat-divider
fxHide.lt-md="true"
fxHide="false"
inset="true"
fxFlex="1 0 15px"
*ngIf="!last"
class="my-0 mx-8"
></mat-divider>
<mat-divider
fxHide.lt-md="false"
fxHide="true"
vertical="true"
inset="true"
fxFlex="1 0 10px"
*ngIf="!last"
class="mx-0 my-4"
></mat-divider>
</ng-container>
</div>
hi i find a solution: this component call "stepper" in angular material have this solucion
example:
HTML
<button mat-raised-button (click)="isLinear = !isLinear" id="toggle-linear">
{{!isLinear ? 'Enable linear mode' : 'Disable linear mode'}}
</button>
<mat-stepper [linear]="isLinear" #stepper>
<mat-step [stepControl]="firstFormGroup">
<form [formGroup]="firstFormGroup">
<ng-template matStepLabel>Fill out your name</ng-template>
<mat-form-field appearance="fill">
<mat-label>Name</mat-label>
<input matInput placeholder="Last name, First name" formControlName="firstCtrl" required>
</mat-form-field>
<div>
<button mat-button matStepperNext>Next</button>
</div>
</form>
</mat-step>
<mat-step [stepControl]="secondFormGroup" label="Fill out your address">
<form [formGroup]="secondFormGroup">
<mat-form-field appearance="fill">
<mat-label>Address</mat-label>
<input matInput formControlName="secondCtrl" placeholder="Ex. 1 Main St, New York, NY" required>
</mat-form-field>
<div>
<button mat-button matStepperPrevious>Back</button>
<button mat-button matStepperNext>Next</button>
</div>
</form>
</mat-step>
<mat-step>
<ng-template matStepLabel>Done</ng-template>
<p>You are now done.</p>
<div>
<button mat-button matStepperPrevious>Back</button>
<button mat-button (click)="stepper.reset()">Reset</button>
</div>
</mat-step>
</mat-stepper>
ts
import { Component } from '#angular/core';
import { FormBuilder, Validators } from '#angular/forms';
/**
* #title Stepper overview
*/
#Component({
selector: 'stepper-overview-example',
templateUrl: 'stepper-overview-example.html',
styleUrls: ['stepper-overview-example.css'],
})
export class StepperOverviewExample {
firstFormGroup = this._formBuilder.group({
firstCtrl: ['', Validators.required],
});
secondFormGroup = this._formBuilder.group({
secondCtrl: ['', Validators.required],
});
isLinear = false;
constructor(private _formBuilder: FormBuilder) { }
}
in here link find you the documentation here https://material.angular.io/components/stepper/overview

how to get value from checkbox when clicked and show it on top of from before submited

I need show my checkbox value when it clicked and show it on top with chips before submited. My checkbox use service for showing the data
I already make a clicked function in my checkbox tag, but its not get the value until i clicked it twice.
my html:
<mat-chip-list #chipList>
<mat-chip color="primary" *ngIf="ars != null" selected>
{{ars}}
<mat-icon matChipRemove (click)="remove(dataForm)">cancel</mat-icon>
</mat-chip>
</mat-chip-list>
</div>
<mat-form-field class="search">
<mat-icon matPrefix>search</mat-icon>
<input
fromControlName="firstName"
type="search"
matInput
placeholder="Search"
/>
</mat-form-field>
<section>
<mat-checkbox value="0" class="" [(ngModel)]="checked" (click)="checkAll">
select all
</mat-checkbox>
</section>
<div *ngFor="let data of formData">
<mat-checkbox [(ngModel)]="data.isSelected"
(click)="submit(formData)"> {{ data.name }} </mat-checkbox>
</div>
my ts file:
this my function for get the value
submit(a) {
for (let i = 0; i < a.length; i++) {
if (a[i].isSelected === true) {
//this.status = this.status + (JSON.stringify(a[i])) ;
// this.arr = [this.status];
this.arr = Object.values(a[i]);
this.ars = this.arr[0];
//this.arr, Validators.required;
}
}
console.log('test for submit', this.ars);
}
I expect the value showing right after clicked, but the value show after the checkbox clicked twice

Reset Angular Formly Form Validations on click event

I am implementing dynamic forms using the angular formly module and It's working fine. What functionality I need is Initially there should be a select box which contains multiple options, Based on selection different form fields should be displayed. As I explained I have Implemented and it's working, here what my problem is If I select option 1 and If I submit the form without filling fields, form displaying validation errors that is also cool. But when I select option 2 form fields are changing, but by default, all required fields are showing errors. How can I resist this? Please suggest me.
html
<div class="row">
<mat-form-field class="col-lg-2">
<mat-select placeholder="Form For" (selectionChange)="getSelectedFormName($event)">
<mat-option value="uf001">UF001</mat-option>
<mat-option value="uf002">UF002</mat-option>
<mat-option value="uf003">UF003</mat-option>
</mat-select>
</mat-form-field>
<div class="col-lg-4">
<button type="button" class="btn btn-default btn-one" (click)="getDynamicForm()">GET FORM</button>
</div>
</div>
<form [formGroup]="form" (ngSubmit)="submit(model)" >
<formly-form [model]="model" [fields]="fields" [form]="form" *ngIf="isFormTypeSelected" >
</formly-form>
<button type="submit" class="btn btn-success">Submit</button>
</form>
ts file
getSelectedFormName(eve) {
this.isFormSaved = false;
this.form = new FormGroup({});
this.fields=[];
this.model = {};
this.parentFormName = eve.value;
}
getDynamicForm() {
this.isFormSaved = false;
this.savedFields=[];
this.getDynamicFormBasedOnSelection(this.parentFormName);
//fields getting from api call
}
getDynamicFormBasedOnSelection(formName: string) {
this.auth.getDynamicFormBasedOnSelction(formName, this.userAgencyCode).subscribe(
(result) => {
const str = JSON.stringify(result);
this.fields = JSON.parse(str);
this.isFormTypeSelected = true;
this.addEvents(this.fields);
});
}
Here I'm providing my screens which are for better understanding
Actually form.reset() just reset the form values. You need to reset the form directive too. for eg.
<form [formGroup]='authForm' (submit)='submitForm(formDirective)' #formDirective="ngForm" class="is-mat-form">
<mat-form-field>
<input matInput placeholder="Email ID" formControlName='login'>
<mat-error *ngIf="authForm.controls.login.hasError('required')">
Email is required
</mat-error>
<mat-error *ngIf="authForm.controls.login.hasError('email')">
Please enter a valid email address
</mat-error>
</mat-form-field>
<mat-form-field>
<input matInput type="password" formControlName='password' placeholder="Password">
<mat-error *ngIf="authForm.controls.password.hasError('required')">
Password is required
</mat-error>
<mat-error *ngIf="authForm.controls.password.hasError('minlength')">
Password must be minimum 6 digit long.
</mat-error>
</mat-form-field>
and .ts file is
submitForm(formDirective: FormGroupDirective){
if (this.authForm.invalid) {
console.log('form submitted')
this.authForm.reset()
return;
}
this will reset the form values only, to reset the form error we need to reset the formdirective as well.
submitForm(formDirective: FormGroupDirective){
if (this.authForm.invalid) {
console.log('form submitted')
this.authForm.reset()
formDirective.resetForm();
return;
}