Posts

Showing posts with the label Angular

Change Icon When Click Button Ionic 2

Answer : You could use *ngIf directive here to show conditional icon. <button clear text-center (click)="toggle()"> <ion-icon name="arrow-drop down-circle" *ngIf="!visible"></ion-icon> <ion-icon name="arrow-drop up-circle" *ngIf="visible"></ion-icon> </button> You could use name property instead of creating two different ion-icon <button clear text-center (click)="toggle()"> <ion-icon [name]="visible ? 'arrow-drop up-circle' :'arrow-drop down-circle'"> </ion-icon> </button> You can create a conditional in the name= attribute <ion-icon [name]="visible ? 'arrow-dropdown' : 'arrow-dropup'"></ion-icon> This took me forever to find since there are very few examples out there for toggling icons. However, I used the Ionic 2 Icons Doc and came up with this: ts: class Toggle...

Angular 2 NgModelChange Old Value

Answer : This might work (ngModelChange)="onModelChange(oldVal, $event); oldVal = $event;" or (ngModelChange)="onModelChange($event)" oldValue:string; onModelChange(event) { if(this.oldValue != event) { ... } this.oldValue = event; } Just for the future we need to observe that [(ngModel)]="hero.name" is just a short-cut that can be de-sugared to: [ngModel]="hero.name" (ngModelChange)="hero.name = $event". So if we de-sugar code we would end up with: <select (ngModelChange)="onModelChange()" [ngModel]="hero.name" (ngModelChange)="hero.name = $event"> or <[ngModel]="hero.name" (ngModelChange)="hero.name = $event" select (ngModelChange)="onModelChange()"> If you inspect the above code you will notice that we end up with 2 ngModelChange events and those need to be executed in some order. Summing up: If you place ngModelChange befor...

Angular: 'Cannot Find A Differ Supporting Object '[object Object]' Of Type 'object'. NgFor Only Supports Binding To Iterables Such As Arrays'

Answer : As the error messages stated, ngFor only supports Iterables such as Array , so you cannot use it for Object . change private extractData(res: Response) { let body = <Afdelingen[]>res.json(); return body || {}; // here you are return an object } to private extractData(res: Response) { let body = <Afdelingen[]>res.json().afdelingen; // return array from json file return body || []; // also return empty array if there is no data } Remember to pipe Observables to async, like *ngFor item of items$ | async , where you are trying to *ngFor item of items$ where items$ is obviously an Observable because you notated it with the $ similar to items$: Observable<IValuePair> , and your assignment may be something like this.items$ = this.someDataService.someMethod<IValuePair>() which returns an Observable of type T. Adding to this... I believe I have used notation like *ngFor item of (items$ | async)?.someProperty You only nee...

Angular 5 Material: Dropdown (select) Required Validation Is Not Working

Answer : Based on the excellent answer of (from zero to hero), I want to clarify 2 points mentioned in comments: 1- You have to use ngModel not value 2- You have to give the control a name Full credit goes to him, I wanted to clarify this to any newcomer like me as it took me 2 hours to find out why it doesn't work You added required to the select's option , not the select . Do it like: <mat-form-field> <mat-select placeholder="Favorite food" name="select" [(ngModel)]="select" required> <mat-option *ngFor="let food of foods" [value]="food.value" > {{ food.viewValue }} </mat-option> </mat-select> </mat-form-field> DEMO

Angular2 NgFor OnPush Change Detection With Array Mutations

Answer : Angular2 change detection doesn't check the contents of arrays or object. A hacky workaround is to just create a copy of the array after mutation this.myArray.push(newItem); this.myArray = this.myArray.slice(); This way this.myArray refers a different array instance and Angular will recognize the change. Another approach is to use an IterableDiffer (for arrays) or KeyValueDiffer (for objects) // inject a differ implementation constructor(differs: KeyValueDiffers) { // store the initial value to compare with this.differ = differs.find({}).create(null); } @Input() data: any; ngDoCheck() { var changes = this.differ.diff(this.data); // check for changes if (changes && this.initialized) { // do something if changes were found } } See also https://github.com/angular/angular/blob/14ee75924b6ae770115f7f260d720efa8bfb576a/modules/%40angular/common/src/directives/ng_class.ts#L122 You might want to use markForCheck method from ChangeDetect...

Angular Material Stepper Component Prevent Going To All The Non Visited Steps

Answer : The solution that I found to this problem is to use completed attribute of step. Refer to the line of code given below: <mat-step [completed]="isCompleted"> When isCompleted is true it will enable the next step. Note: For this to work, the stepper component must be in the linear mode. This can be done by setting the attribute linear on the stepper component, like <mat-horizontal-stepper linear> Check this link . You need to use linear stepper. A stepper marked as linear requires the user to complete previous steps before proceeding. For each step, the stepControl attribute can be set to the top level AbstractControl that is used to check the validity of the step. Example shown as below import { Component, Input } from '@angular/core'; import {FormBuilder, FormGroup, Validators} from '@angular/forms'; import {MatIconRegistry} from '@angular/material'; @Component({ selector: 'stepper', te...

Angular 2 Custom Validator That Depends On Another Form Control

Answer : You are one step closer. You need to attach your custom validator to the FormGroup instead, because it needs to know two FormControl ( categories and mealTypes ), so attaching to FormGroup will give the validator more broad view and access to the entire FormControl To achieve that, change your ngOnInit to ngOnInit() { this.findForm = new FormGroup({ mealTypes : new FormControl(null, Validators.Required), categories : new FormControl(null) // others form control here }, validateMealType); // <-- see here is your custom function } On above code, you actually have to use FormGroup constructor instead of FormBuilder , so you can attach your custom validation in the parameters. Also, move your custom validator outside the component class. Take a look at this Plunker to get more insight for your specific case here. The solution proposed by @Michael worked for me with a minor change for the Angular 4. In the validation function...

Angular 2 - Debouncing A KeyUp Event

Answer : UPDATE: Using RXJS 6 pipe operator: this.subject.pipe( debounceTime(500) ).subscribe(searchTextValue => { this.handleSearch(searchTextValue); }); You could create a rxjs/Subject and call .next() on keyup and subscribe to it with your desired debounceTime. I'm not sure if it is the right way to do it but it works. private subject: Subject<string> = new Subject(); ngOnInit() { this.subject.debounceTime(500).subscribe(searchTextValue => { this.handleSearch(searchTextValue); }); } onKeyUp(searchTextValue: string){ this.subject.next(searchTextValue); } HTML: <input (keyup)="onKeyUp(searchText.value)"> An Update for Rx/JS 6. Using the Pipe Operator. import { debounceTime } from 'rxjs/operators'; this.subject.pipe( debounceTime(500) ).subscribe(searchTextValue => { this.handleSearch(searchTextValue); }); Everything else is the same

Angular 2 Http.post() Is Not Sending The Request

Answer : Since the post method of the Http class returns an observable you need to subscribe it to execute its initialization processing. Observables are lazy. You should have a look at this video for more details: https://egghead.io/lessons/rxjs-rxjs-observables-vs-promises You must subscribe to the returned observable if you want the call to execute. See also the Http documentation. Always subscribe! An HttpClient method does not begin its HTTP request until you call subscribe() on the observable returned by that method. This is true for all HttpClient methods . The AsyncPipe subscribes (and unsubscribes) for you automatically. All observables returned from HttpClient methods are cold by design. Execution of the HTTP request is deferred , allowing you to extend the observable with additional operations such as tap and catchError before anything actually happens. Calling subscribe(...) triggers execution of the observable and causes HttpClient to compose an...

Change SVG Size In Angular Material 2 Using Vanilla CSS Or HTML

Answer : It seems that library styles override your css inline declaration. Try maybe to add !important declaration to your style: style="font-size: 16 !important" or since you didn't provide more code, try to inspect this icon node, to check which style define the font-size. Also check here UPDATE : Here is another possibly working solution. Add transform: scale(2); style for svg element you want to resize, where 2 is 200% of actual size (of course you can also downsize them using for example 0.5 value for 50%). Here is working sample for the website with your icons and link to documnetation: .size-24 button svg { width: 24px; height: 24px; transform: scale(2); } I played with this for way too long. I have a series of icons that I want to be scaled to fit in various mat-icon sizes, but each icon needs a different scale so they appear balanced with the other icons - effectively increasing the size of the viewBox. In the end this worked well...

Angular 2 Get Parent Activated Route

Answer : You can do this by using the parent property on the ActivatedRoute - something like this. export class MyComponent implement OnInit { constructor(private activatedRoute: ActivatedRoute) {} ngOnInit() { this.activatedRoute.parent.url.subscribe((urlPath) => { const url = urlPath[urlPath.length - 1].path; }) } } You can see everything from the ActivatedRoute in more detail here: https://angular.io/api/router/ActivatedRoute You can check for parent route by determining if only one slash is present in it: constructor(private router: Router) {} ngOnInit() { this.router.events.pipe(filter(e => e instanceof NavigationEnd)).subscribe((x: any) => { if (this.isParentComponentRoute(x.url)) { // logic if parent main/parent route } }); } isParentComponentRoute(url: string): boolean { return ( url .split('') .reduce((acc: number, curr: string) ...

Angular Unit Test Input Value

Answer : Inputs don't have textContent, only a value. So expect(field.textContent).toBe('someValue'); is useless. That's probably what's failing. The second expectation should pass though. Here's a complete test. @Component({ template: `<input type="text" [(ngModel)]="user.username"/>` }) class TestComponent { user = { username: 'peeskillet' }; } describe('component: TestComponent', () => { beforeEach(() => { TestBed.configureTestingModule({ imports: [FormsModule], declarations: [ TestComponent ] }); }); it('should be ok', async(() => { let fixture = TestBed.createComponent(TestComponent); fixture.detectChanges(); fixture.whenStable().then(() => { let input = fixture.debugElement.query(By.css('input')); let el = input.nativeElement; expect(el.value).toBe('peeskillet'); el.value = 'someValue'; el.d...

Angular's Ng-init Alternative In Angular 2

Answer : You can use a directive @Directive({ selector: 'ngInit', exportAs: 'ngInit' }) export class NgInit { @Input() values: any = {}; @Input() ngInit; ngOnInit() { if(this.ngInit) { this.ngInit(); } } } you can use it to pass a function to be called like <div [ngInit]="doSomething" or to make values available <div ngInit [values]="{a: 'a', b: 'b'}" #ngInit="ngInit"> <button (click)="clickHandler(ngInit.values.a)">click me</button> </div> ngInit addes the directive [values]="{a: 'a', b: 'b'}" sets some initial values #ngInit="ngInit" creates a reference for later use ngInit.values.a reads the a value from the created reference. See also Converting Angular 1 to Angular 2 ngInit function Another approach is by using the @Output decorator and EventEmitter: import {Directive, OnInit, Output, EventEmitter...

Angular 2+ Attr.disabled Is Not Working For Div When I Try To Iterate NgFor Loop

Answer : Use [disabled] instead of [attr.disabled] This is because [attr.disabled]="false" will add disabled="false" to the element which in html, will still disable the element Syntax that will not disable an element <button>Not Disabled</button> <button [disabled]="false">Not Disabled</button> Syntax that will disable an element <button disabled></button> <button disabled="true"></button> <button disabled="false"></button> <button [attr.disabled]="true"></button> <button [attr.disabled]="false"></button> <button [disabled]="true"></button> disabled will disable an element whether it is true or false, it's presence means that the element will be disabled. Angular will not add the disabled element at all for [disabled]="variable" if variable is false. As you mentioned in your...

Angular Testing For Angular-Material On Mat-Menu

Answer : My final test ended up looking like this: import { TestBed, async, ComponentFixture } from '@angular/core/testing'; import { AppComponent } from './app.component'; import { RouterTestingModule } from '@angular/router/testing'; import { AppRoutes } from './app.routes'; import { MatToolbarModule, MatIconModule, MatMenuModule, MatButtonModule } from '@angular/material'; import { HomeComponent } from './home/home.component'; import { UserService } from './user/user.service'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { BehaviorSubject } from '../../node_modules/rxjs'; class MockUserService { signedIn$: BehaviorSubject<boolean> = new BehaviorSubject(false); signIn() {} } describe('AppComponent', () => { let app: AppComponent; let fixture: ComponentFixture<AppComponent>; let dom; let button; beforeEach(async(() => ...

Add Data To The End Of A Behavior Object Array Angular 5

Answer : You can add a new method to your service like addData in which you can combine your previous data with new data like. import {Injectable} from '@angular/core'; import {BehaviorSubject} from 'rxjs/BehaviorSubject'; @Injectable() export class UserService { userDataSource: BehaviorSubject<Array<any>> = new BehaviorSubject([]); userData = this.userDataSource.asObservable(); updateUserData(data) { this.userDataSource.next(data); } addData(dataObj) { const currentValue = this.userDataSource.value; const updatedValue = [...currentValue, dataObj]; this.userDataSource.next(updatedValue); } } For someone that may come accross this issue with a BehaviorSubject<YourObject[]> . I found in this article a way to properly add the new array of YourObject import { Observable, BehaviorSubject } from 'rxjs'; import { YourObject} from './location'; import { Injectable } from ...

Cannot Uninstall Angular-cli

Answer : I have also faced the same issue in recent past for me I have do the following commands one by one in terminal. sudo npm uninstall -g angular-cli sudo npm cache clean After this run ng -v If still get angular-cli version 1.0.0-beta.2x.x then run the following command which ng It will show the ng path. Go to the path and if it is linked with any file remove the same the link and actual ng file. In my case the link is in /usr/bin/ng and actual path of ng file is /lib/node_modules/@angular/cli/bin/ng. sudo rm -rf /lib/node_modules/@angular/cli/bin/ng sudo rm -rf /usr/bin/ng Next you need to install @angular/cli using sudo npm install -g @angular/cli Close all the terminal and run ng -v and you are on. May be it will help someone. Thanks :) Updating Angular CLI https://github.com/angular/angular-cli#updating-angular-cli If you're using Angular CLI 1.0.0-beta.28 or less, you need to uninstall angular-cli package first. npm uninstall -g angular-cli ...

Angular (5) Httpclient Observe And ResponseType: 'blob'

Answer : When using observe:response , don't type the call ( post<Blob>(...) ), as the returned Observable will be of HttpResponse. So this should work: this.httpclient.post('MyBackendUrl', params, {observe: 'response', responseType: 'blob'} ); Why this happens, is there's two versions of the post method, one with a generic type, one without: /** * Construct a POST request which interprets the body as JSON and returns the full event stream. * * @return an `Observable` of all `HttpEvent`s for the request, with a body type of `T`. */ post<T>(url: string, body: any | null, options: { headers?: HttpHeaders | { [header: string]: string | string[]; }; observe: 'events'; params?: HttpParams | { [param: string]: string | string[]; }; reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean...

Changing Border Color In Mat-form-field

Answer : I think this will cover everything. // mat-icon-stepper selected color change ::ng-deep .mat-step-header .mat-step-icon-selected, .mat-step-header .mat-step-icon-state-done, .mat-step-header .mat-step-icon-state-edit { background-color: red!important; } //input outline color ::ng-deep .mat-form-field-appearance-outline .mat-form-field-outline { color: red!important; // opacity: 1!important; } //mat-input focused color ::ng-deep .mat-form-field-appearance-outline.mat-focused .mat-form-field-outline-thick { color: red!important; } // mat-input error outline color ::ng-deep .mat-form-field-appearance-outline.mat-form-field-invalid.mat-form-field-invalid .mat-form-field-outline-thick{ color: red!important; opacity: 0.8!important; } // mat-input carent color ::ng-deep .mat-input-element { caret-color: red!important; } // mat-input error carent color ::ng-deep .mat-form-field-invalid .mat-input-element, .mat-warn .mat-input-element { caret-...

Angular2: Web Speech API - Voice Recognition

Answer : Finally I solved creating an interface !! export interface IWindow extends Window { webkitSpeechRecognition: any; } And: const {webkitSpeechRecognition} : IWindow = <IWindow>window; const recognition = new webkitSpeechRecognition(); In Angular 9, it worked me but using const speechRecognition = window['webkitSpeechRecognition']; note that the window 'w' is lowercase.