ngx-mat-select-search is not loading the data in dropdown after init - angular12

Reference used:
https://stackblitz.com/edit/github-yn8zve-xl2vcs?file=src%2Fapp%2Fexamples%2F01-single-selection-example%2Fsingle-selection-example.component.ts
Values are loaded into countrydropdown but after I am clicking it for first time . After that all is working fine . only concern is value not loading at the page loads .
here is the typescript:
ngOnInit(): void {
this.orgNameSearchInit();
this.getCountryCodes();
// load the initial bank list
console.log("inside nginit ")
this.countryArrFilterDropdown.next(this.countryArray.slice());
//to listen any change in search box
this.searchFormControl.valueChanges
.pipe(takeUntil(this._onDestroy))
.subscribe(() => {
this.filterCodes();
});
}
protected filterCodes() {
if (!this.countryArray) {
return;
}
// get the search keyword
let search = this.searchFormControl.value;
console.log("searched value: "+ search);
if (!search) {
console.log(this.countryArrFilterDropdown.next(this.countryArray.slice()));
this.countryArrFilterDropdown.next(this.countryArray.slice());
return;
} else {
search = search.toLowerCase();
}
console.log("after ifelse");
// filter the Country
this.countryArrFilterDropdown.next(
this.countryArray.filter((countrys) => countrys.countryName.toLowerCase().indexOf(search) > -1)
// this.banks.filter((bank) => bank.name.toLowerCase().indexOf(search) > -1)
);
}
ngAfterViewInit(): void {
this.setInitialValue();}
here is the html :
<div class="col-sm-2">
<mat-form-field>
<mat-select [formControl]="testFormControl" placeholder="Code" #singleSelect>
<mat-option>
<ngx-mat-select-search [formControl]="searchFormControl" placeholderLabel="Search"></ngx-mat-select-search>
</mat-option>
<mat-option *ngFor="let countryArrFilterDropdowns of countryArrFilterDropdown | async"
[value]="countryArrFilterDropdowns.countryCode">
{{countryArrFilterDropdowns.countryName}}
</mat-option>
</mat-select>
</mat-form-field>
</div>

Related

Perform actions on component initialization in LWC

I recently started learning LWC. I am working on a requirement in LWC where on component initialization I need to use record Id to get value of numeric field from same object/record, check if it is 100 and display a message on component html. Note - this LWC is used as a quick action of type Screen Action. Following is current implementation which works at times and doesn't (not sure if it is a cache issue).
LWCComponent.html
<template>
<!-- modal start -->
<template if:true={isShowModal}>
<lightning-quick-action-panel header="New Record">
<div class="slds-modal__content modalBodySpinner" style="width: 100%;" id="modal-content-id-1">
<template if:true={isLoaded}>
<lightning-spinner alternative-text="Loading" size="medium" class="spinnerClass"></lightning-spinner>
</template>
<div slot>
<lightning-layout>
<lightning-layout-item size="6" padding="around-small">
<lightning-input label="Record Name" type = "text" value={recordName}></lightning-input>
</lightning-layout-item>
</lightning-layout>
</div>
<template if:true={recordId}></template>
<template if:true={showForm}>
<lightning-input label="Record ID" type="text"></lightning-input>
</template>
<template if:false={showForm}>
<p class="warningP">{restrictMessage}</p>
</template>
<br/>
</div>
<div slot="footer">
<lightning-button variant="neutral" label="Cancel" onclick={closeModal}></lightning-button>
</div>
</lightning-quick-action-panel>
</template>
<!-- modal end -->
</template>
LWCComponent.js
import { LightningElement, track, api, wire } from 'lwc';
import { getRecord, getFieldValue } from "lightning/uiRecordApi";
import NAME from "#salesforce/schema/CustomObject__c.Name";
import CAPACITY from "#salesforce/schema/CustomObject__c.Capacity__c";
import { CloseActionScreenEvent } from 'lightning/actions';
import restrictMessage from "#salesforce/label/c.RestrictWarning";
const fields = [NAME, CAPACITY];
export default class NewClass extends LightningElement {
#track isShowModal = true;
#track showForm = true;
#api recordId;
#track isLoaded = true;
#api capacityVal;
#track warningMsg;
#track retrievedRecordId = false;
#wire(getRecord, {
recordId: "$recordId",
fields
})
custObjRec;
get recordName() {
return getFieldValue(this.custObjRec.data, NAME);
}
renderedCallback() {
if(!this.retrievedRecordId && this.recordId) {
this.retrievedRecordId = true;
this.capacityVal = getFieldValue(this.custObjRec.data, CAPACITY)
if(this.capacityVal == 100) {
this.showForm = false;
this.warningMsg = restrictMessage;
this.isLoaded = false;
}
else {
this.isLoaded = false;
}
}
else {
this.isLoaded = false;
}
}
// method to close modal pop up
closeModal() {
this.dispatchEvent(new CloseActionScreenEvent());
}
}
Any suggestions to make this better?

angulare material datepicker problem with dateclass()

i am using angular's datepicker to create a booking service.
I am experiencing a huge problem, when I make the reservation I activate a dialog that confirms the outcome of the reservation, if the outcome is positive another dialog opens with the confirmation. when you click on the button 'ok', to close the final dialogue and return to the datepicker, a call starts that takes all the customer's reservations and colors the dates blue.
here the chaos happens:
the dateClass () method inside the appcomponent.ts file is activated several times and cycles the old reservation list and not the new one.
I attached the code:
APPCOMPONENT.HTML
<mat-form-field class="example-full-width" appearance="fill">
<mat-label>Clicca sul calendario</mat-label>
<input matInput readonly [matDatepicker]="picker" [(ngModel)]="this.shareDate.myFormattedDate" (dateChange)="openDialog($event)">
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
<mat-datepicker [dateClass]="dateClass()" #picker> </mat-datepicker>
</mat-form-field>
APPCOMPONENT.TS
dateClass() {
return (date: Date): MatCalendarCellCssClasses => {
const unvailableArray = this.shareDate.unavailableDates;
const reservedArray = this.shareDate.reservedDate;
let day = 'freeDate';
for (const element of reservedArray) {
if (date.getFullYear() === element.getFullYear() && date.getMonth() === element.getMonth() &&
date.getDate() === element.getDate()) {
day = 'prenotation';
return day;
}
}
for (const element of unvailableArray) {
if (date.getFullYear() === element.getFullYear() && date.getMonth() === element.getMonth() &&
date.getDate() === element.getDate()) {
day = 'unavailable';
return day;
}
}
return day;
};
}
dialogConfirm.ts
click() {
const devCode = this.getQueryCode.getQueryParameter('d');
this.shareDate.device.deviceId = devCode;
this.postservices.getPrenotationList(this.shareDate.device).subscribe((resp1: GetDataResponse) => {
if (resp1) {
this.shareDate.foundDate = resp1;
for (const element of this.shareDate.foundDate.reservationdDates) {
this.shareDate.reservedDate.push(new Date(element));
}
}
console.log('resp1', resp1);
});
this.postservices.getPrenotationList(this.shareDate.device).subscribe((resp1: GetDataResponse) => {
if (resp1) {
this.shareDate.foundDate = resp1;
for (const element of this.shareDate.foundDate.unavailableDates) {
this.shareDate.unavailableDates.push(new Date(element));
}
}
});
}
I put console.log (), in the dateclass () and in click () when dateclass () starts, the log shows me that I have 3 reservations, when I make a reservation the click () log tells me that I have 4 reservations. but when I close the dialogue, dateclass () activates again and returns me to 3 reservations. if I close and restart the app it shows me 4 reservations ... what happens? what do I have to do?
Don't call function in template.Since dataClass input property expects MatCalendarCellClassFunction,assign function to dateClass property something like this.
component.ts
dateClass = (date: Date): MatCalendarCellCssClasses => {
const unvailableArray = this.shareDate.unavailableDates;
const reservedArray = this.shareDate.reservedDate;
let day = 'freeDate';
for (const element of reservedArray) {
if (date.getFullYear() === element.getFullYear() && date.getMonth() === element.getMonth() &&
date.getDate() === element.getDate()) {
day = 'prenotation';
return day;
}
}
for (const element of unvailableArray) {
if (date.getFullYear() === element.getFullYear() && date.getMonth() === element.getMonth() &&
date.getDate() === element.getDate()) {
day = 'unavailable';
return day;
}
}
return day;
};
component.ts
<mat-form-field class="example-full-width" appearance="fill">
<mat-label>Clicca sul calendario</mat-label>
<input matInput readonly [matDatepicker]="picker" [(ngModel)]="this.shareDate.myFormattedDate" (dateChange)="openDialog($event)">
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
<mat-datepicker [dateClass]="dateClass" #picker> </mat-datepicker>
</mat-form-field>

Why nzBeforeUpload with option multiple is called multiple times

I'm using Angular 10 and ng-zorro and I am using nz-upload component, and I have a question:
Why beforeUpload is called equal to files uploaded? if we have a nzFileUpload[] parameter, its like a repetition not wanted
My .html code:
<div>
<nz-upload
ngDefaultControl
nzType="drag"
(click)="form.get('files').markAsTouched()"
[nzDirectory]="false"
[nzBeforeUpload]="beforeUpload"
[nzDisabled]="false"
[nzLimit]="fileMaxQuantity"
[nzSize]="0"
[nzListType]="'text'"
[nzMultiple]="true"
[nzShowUploadList]="false"
[nzShowButton]="false"
(nzChange)="handleChange($event)"
>
<p class="ant-upload-drag-icon" style="margin-bottom: unset;">
<i nz-icon nzType="cloud-upload"></i>
</p>
<p class="ant-upload-text">{{ '::FileUpload:FilesUploadMessage' | abpLocalization }}
</p>
<p class="ant-upload-hint">
{{ '::FileUpload:FilesUploadHint' | abpLocalization }}
</p>
</nz-upload>
<mat-error *ngIf="form.get('files').hasError('required') && form.get('files').touched">
{{ '::FileUpload:FilesFieldRequired' | abpLocalization}}
</mat-error>
</div>
And my .ts (beforeupload):
beforeUpload = (singleFile: File, fileList: File[]): boolean => {
// if (this.form.controls.files as FormArray)
const fileNames = this.form.controls.fileNames.value as [];
if (fileNames.length === this.fileMaxQuantity) {
this.snackBarService.warning(this.localizationService.instant('::FileUpload:NumberFilesExceedsAllowed'), true);
return false;
} else {
for (let i = 0; i <= fileList.length; i++) {
const file = fileList[i];
// _.each(fileList, (file) => {
if (this.form.controls.fileNames.value.length === this.fileMaxQuantity) {
this.snackBarService.warning(this.localizationService.instant('::FileUpload:NumberFilesExceedsAllowed'));
break;
// return false;
} else {
const tempStackSize = this.actualFileStackSize + file.size;
if (file.size > this.fileMaxSize || tempStackSize > this.fileMaxSize) {
this.snackBarService.warning(this.localizationService.instant('::FileUpload:FileTooHeavy'), true);
return false;
} else if ( !this.fileList.some( p => p.name === file.name ) ) {
const ext = this.extensionPipe.transform(file.name);
let control: FormControl;
(this.form.controls.files as FormArray).push(new FormControl(file.name));
(!this.regexWithExt.test(file.name)) ?
this.fileListRequired.push(true) : // debe cambiar filename
this.fileListRequired.push(false);
control = new FormControl(file.name.replace(ext, ''),
[ Validators.pattern(this.regex),
Validators.required,
Validators.maxLength(this.fileNameMaxLength - ext.length),
this.fileNameValidator()]);
control.markAllAsTouched();
(this.form.controls.fileNames as FormArray).push(control);
// fileNames.push(file.name);
this.fileList.push(file);
this.actualFileStackSize = tempStackSize;
}
}
}
// fileList.forEach((file) => {
// });
}
return false;
}
From the above, the problem is that this function beforeUpload is called equal to list size of files.

Angular - Change BackGround Color of Row in Table After click the Buttom

I want change the background color of the selected row after click the button
I tried but change the color of all rows.
This is a similar code.
HTML
<tr *ngFor="let data of (datas$ | async) | filter:authService.filter | paginate: config | orderBy: key : reverse" [ngClass]="{'data-selected':isSelected}">
<td>{{data.id}}</td>
<td>{{data.text}}</td>
<td>
<a class="mr-3" (click)="delete(data.id)"><i class="fa fa-remove"></i>
Remove
</a>
</td>
</tr>
TS
delete(postId) {
this.isSelected=true;
const ans = confirm('TEXT TEXT '+dataid);
if (ans) {
this.dataService.deleteData(postId).subscribe((data) => {
if(data) {
this.showSuccessDelete();
} else {
this.showError();
}
this.isSelected=false;
this.loadDatas();
});
}
}
CSS
.data-selected{
background-color: #e9eaea;
}
Thanks so much
You can add an attribute to your component class and call it selectedRow, which will get the data.id.
selectedRow: number;
delete(postId,numeroDeposito) {
this.selectedRow = postId;
const ans = confirm('TEXT TEXT '+dataid);
if (ans) {
this.dataService.deleteData(postId).subscribe((data) => {
if(data) {
this.showSuccessDelete();
} else {
this.showError();
}
this.isSelected=false;
this.loadDatas();
});
}
}
then in the tr tag use [ngClass]="{'data-selected': selectedRow === data.id}".
You can also take the following approach:
Working Demo
[class.data-selected]="data.isSelected"
and On click event.
(click)="data.isSelected = true";
Rather than declaring a separate isSelected variable. you should introduce is as a property of data object. Ex:
{
id: 1,
name: 'AA',
isSelected: false
}
Then on click you can toggle it when delete function is called with data.id as parameter.
deleteMe(id: string) {
this.data.map(x => x.isSelected = false);
this.data.find(x => x.id === id).isSelected = true;
}
And in html
<tr *ngFor="let item of data" [ngClass]="{selected: item.isSelected}">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td><button (click)="deleteMe(item.id)">delete me</button></td>
</tr>
Here is a minimum example.
You can use conditional styling to achieve this.
<div [className]="( checkSelectedRow(i) ? 'example-class' : 'other-class'"></div>
In Typescript file:
checkSelectedRow(rowNumber) : boolean {
for(int j=0; j<rows.length; j++){
if(j==i){
rows[i]["selected"]=true; return true;
};
}
return false;
}
this can be solve by create an array of selected rows like this
deleteList = []
then when you click remove push the id of the item in the list
delete(id) {
this.deleteList.push(id)
}
then at the template use ngClass directive to set the class if the item id include in the list
<tr *ngFor="let data of list" [ngClass]="{'data-selected':deleteList.includes(data.id)}">
....
</tr>
demo 🚀🚀

Is it possible to extract specific CSS property from one css file to another?

I'm wondering, is there any way that I can exclude or extract some specific CSS properties from one CSS file to another?
For example, I have a style.css file, from which I only want to extract all the background and color properties to another CSS file. Is it possible in any way?
TIA
Found a solution at last!
This kinda works but needs more tweaks and improvements.
let at_data='';
var css=[];
var openFile=function(event) {
var input=event.target;
var reader=new FileReader();
reader.onload=function() {
var text=reader.result;
var node=document.getElementById('output');
//node.innerText=text;
at_data=reader.result.substring();
at_data.split('}').map(item=> {
var item2=item.trim();
var item3=(item2 +"}");
css.push(item3)
}
);
css.pop();
//console.log(css);
}
;
reader.readAsText(input.files[0]);
}
;
//console.log(css)
function getCss (property,
value) {
const filter=css.filter(function(item, index) {
const filter2=item.split('{')[1].split(';').filter(function(item2, index) {
if(item2.trim().startsWith(property)) {
if(item2.split(':')[1] !==undefined) {
if(item2.split(':')[1].trim().startsWith(value)) {
return item2
}
}
}
}
);
return item.includes(filter2[0]);
}
);
var data1='';
filter.map(data=> {
data1 +='<p>'+data+'</p>'
}
);
data1 +='';
document.getElementById('article').innerHTML=data1;
}
var btn=document.getElementById('getStyle');
btn.addEventListener('click',
function () {
let pro=document.getElementById('property').value, value=document.getElementById('value').value;
getCss(pro, value)
}
);
<input type='file' onchange='openFile(event)'><br>
<div id='output'></div>
<input type="text" id='property' value='' placeholder="property">
<input type="text" id='value' value='' placeholder="value">
<button id="getStyle">Click</button>
<article id="article"></article>

Resources