Posts

Showing posts with the label Angular

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

Creating An RxJS Observable From A (server Sent) EventSource

Answer : You could use the following code to manually create Observable for EventSource stream: export class AppComponent implements OnInit { someStrings:string[] = []; constructor(private zone: NgZone) {} ngOnInit(){ const observable = Observable.create(observer => { const eventSource = new EventSource('/interval-sse-observable'); eventSource.onmessage = x => observer.next(x.data); eventSource.onerror = x => observer.error(x); return () => { eventSource.close(); }; }); this.subscription = observable.subscribe({ next: guid => { this.zone.run(() => this.someStrings.push(guid)); }, error: err => console.error('something wrong occurred: ' + err) }); } } // somewhere // this.subscription.unsubscribe() Don't forget to import the NgZone class: import {Component, OnInit, NgZone} from '@angular/core'; See also Angular2 View Not Changing After Data Is Updat...

Ag-Grid Header Styles Not Changing With CSS On Component

Answer : Try using ::ng-deep combinator https://angular.io/guide/component-styles#deprecated-deep--and-ng-deep ::ng-deep .ag-theme-balham .ag-header { background-color: #e0e0e0; } If that does not work, put your css in the global stylesheet and check if the styles are overriden correctly Override the header-cell class instead .ag-theme-balham .ag-header-cell{ background-color: #e0e0e0; } and if you have header-group then .ag-theme-balham .ag-header-cell, .ag-theme-balham .ag-header-group-cell{ background-color: #e0e0e0; }

Angular Start NgFor Index From 1

Answer : *ngFor="let item of items | slice:1; let i = index; SlicePipe There are 2 possible answers to the question, depending on what was actually being asked. If the intent is to skip the first element of the array, then the answers involving slice are in the right direction. However, if the intent is to simply shift the index while still iterating over all of the array, then slice is NOT the correct approach, as it will skip the 0th element in the array, thereby outputting only n-1 items from an array of length n . @Taylor gave a real-world example of when the index might need to be shifted for display purposes, such as when outputting a list where the first entry should read 1, not 0. Here's another similar example: <li *ngFor="let book of books; let i = index"> {{ i + 1 }}. {{ book.title }} </li> which would produce output like: Sample Book Title Another book title ... That's not possible, but you could use Arr...

Angular: Scroll Dynamic Element Into View Knowing Only Its ID

Answer : You want the id to be on the actual item that the ng-for creates, not the ng-for itself. That would eliminate the need for any extra logic when passing data to the list from the component. // inside ngAfterViewInit() to make sure the list items render or inside ngAfterViewChecked() if you are anticipating live data using @Inputs const itemToScrollTo = document.getElementById('item-' + id); // null check to ensure that the element actually exists if (itemToScrollTo) { itemToScrollTo.scrollIntoView(true); } <div class="list" *ngFor="let item of functionThatGetsItems(); let i = index"> <div class="list-item" id="item-{{i}}"> <div class="title"> {{ item.title }} </div> <div class="content"> {{ item.content }} </div> </div> </div> This is not strictly angular, but you could do document.querySelector('#MyList31'...

Angular - Wait Until I Receive Data Before Loading Template

Answer : After studying the different approaches that people gave me, I found the solution on the async pipe. But, it took me a while to understand how to implement it. Solution: // Declaring the Promise, yes! Promise! filtersLoaded: Promise<boolean>; // Later in the Component, where I gather the data, I set the resolve() of the Promise this.getFiltersSubscription = this.getFilters().subscribe( (filters) => { this.filters = filters; log.info('API CALL. getting filters'); this.filtersLoaded = Promise.resolve(true); // Setting the Promise as resolved after I have the needed data } ); // In this listener triggered by the dynamic components when instanced, // I pass the data, knowing that is defined because of the template change // Listens to field's init and creates the fieldset triggering a service call // that will be listened by the field component this.iboService.initIBOsFilters$.subscribe( (fieldName) => { ...

Angular2 Multiple Constructor Implementations Are Not Allowed TS2392

Answer : Making multiple constructors with the same parameters doesn't make sense unless they have different types, in Typescript you can do the following: class Foo { questions: any[]; constructor(service: QuestionSignupStepOneService, param2?: Param2Type) { this.questions = service.getQuestions(); if(param2){ console.log(param2); } } } This is equal to two constructors, the first one is new Foo(service) and the second one is new Foo(service, param2) . Use ? to state that the parameter is optional. If you want two constructors with the same parameter but for different types you can use this: class Foo { questions: any[]; constructor(service: QuestionSignupStepOneService | QuestionSignupStepOneAService) { if(service instanceof QuestionSignupStepOneService){ this.questions = service.getQuestions(); } else { this.questions = service.getDifferentQuestions(); } } }

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-material: Input-group And Md-buttons On Same Line

Answer : Try the following code: <form layout layout-align="center" layout-padding> <div layout="row" flex> <md-input-container flex class="md-icon-float md-block md-title"> <label>Your font number</label> <!-- below is the material icons --> <md-icon class="material-icons">phone</md-icon> <input type="text"> </md-input-container> <div> <md-button class="md-raised"> <!-- below is the material icons --> <md-icon class="material-icons">search</md-icon> </md-button> </div> </div> </form> see a sample in the following link http://codepen.io/cmwang-cottageclothing/pen/BjpdVQ?editors=1000 Would like to provide a contemporary answer to this popular question. 1...

Angular Material: Mat-select Not Selecting Default

Answer : Use a binding for the value in your template. value="{{ option.id }}" should be [value]="option.id" And in your selected value use ngModel instead of value . <mat-select [(value)]="selected2"> should be <mat-select [(ngModel)]="selected2"> Complete code: <div> <mat-select [(ngModel)]="selected2"> <mat-option *ngFor="let option of options2" [value]="option.id">{{ option.name }}</mat-option> </mat-select> </div> On a side note as of version 2.0.0-beta.12 the material select now accepts a mat-form-field element as the parent element so it is consistent with the other material input controls. Replace the div element with mat-form-field element after you upgrade. <mat-form-field> <mat-select [(ngModel)]="selected2"> <mat-option *ngFor="let option of options2" [value]="option.id...

Angular 5, NullInjectorError: No Provider For Service

Answer : You need to add TesteventService under providers under imports in your app.module.ts providers: [ TesteventService ] Annotate your service class with - @Injectable({ providedIn: 'root' }) The service itself is a class that the CLI generated and that's decorated with @Injectable() . By default, this decorator has a providedIn property, which creates a provider for the service. In this case, providedIn: 'root' specifies that Angular should provide the service in the root injector.

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 Cli - How To Disable Auto Reload When Ng Serve

Answer : Just do ng serve --live-reload false or ng serve --no-live-reload It used to not work, this PR solved it. serve your application with this command: ng serve --live-reload=false if you want to run your application in prod mode , use following command ng serve --source-map=false --aot --prod --live-reload=false I think you only want to disable the rebuild on change option Just try: $ ng serve --watch=true|false

Angular Form Builder Vs Form Control And Form Group

Answer : I have gone through the Angular Official Docs and on the Reactive Forms Part I have seen that: The FormBuilder service is an injectable provider that is provided with the reactive forms module. If you read more you see that the form builder is a service that does the same things as form-group, form-control and form-array. The official docs describe it as: Creating form control instances manually can become repetitive when dealing with multiple forms. The FormBuilder service provides convenient methods for generating controls. So basically saying that FormBuilder is a service that is trying to help us reduce boiler-plate code. An example of how FormBuilder is used to reduce boilerplate code can be seen here. To answer the question: So is there any advantage of one over the other way of doing it or is it just preference? Well, there is no technical advantage and whichever code you use all boils down to your preference. This example is here With FormControl: c...

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(() => ...

Angular Service Worker SwUpdate.available Not Triggered

Answer : You will probably need to tell the service worker to check the server for updates, I usually use a service for this: export class UpdateService { constructor(public updates: SwUpdate) { if (updates.isEnabled) { interval(6 * 60 * 60).subscribe(() => updates.checkForUpdate() .then(() => console.log('checking for updates'))); } } public checkForUpdates(): void { this.updates.available.subscribe(event => this.promptUser()); } private promptUser(): void { console.log('updating to new version'); this.updates.activateUpdate().then(() => document.location.reload()); } In your app-component.ts : constructor(private sw: UpdateService) { // check the service worker for updates this.sw.checkForUpdates(); } For whatever reason, Angular sometimes does not register the service worker properly. So you can modify `main.ts` : Replace: platformBrowserDynamic().bootstrapModule(AppModule); With: p...

Angular 2 Material Design Expand All / Collapse All

Image
Answer : 1- You should remove the mat-accordion to enable multiple expanded panels. 2- Use the expanded parameter to change multiple states at the same time. Here is a running example. EDIT From version 6.0.0-beta-0 you can use multi parameter and the openAll and closeAll functions : 1- Change the mat-accordion element to set the muti to true and get the MatAccordionComponent instance : <mat-accordion #accordion="matAccordion" [multi]="true"> 2- Then use the openAll and closeAll functions to open or close all panels : <button (click)="accordion.openAll()">Expand All </button> <button (click)="accordion.closeAll()">Collapse All </button> Here is a running example. Source Link For the latest version of Angular material 8 Template <button mat-flat-button color="primary" (click)="openAllPanels()"><b>Open Panels</b></button> &nbsp; ...

Angular: Convert XML To JSON

Image
Answer : If you use angular-cli to bootstrap your application - it comes already with node module to convert xml. https://github.com/Leonidas-from-XIV/node-xml2js So you do not need to add extra modules for this. As it is classic commonJS module - you need use require to import it: let parseString = require('xml2js').parseString; So your code can looks like: let parseString = require('xml2js').parseString; let xml = "<root>Hello xml2js!</root>" parseString(xml, function (err, result) { console.dir(result); }); You will receive next output: In any cases - if you even do not use angular-clior want to use your preffered module to parse xml - use require to load it. function parseXml(xmlStr) { var result; var parser = require('xml2js'); parser.Parser().parseString(xmlStr, (e, r) => {result = r}); return result; }

Angular-Material Sidenav CdkScrollable

Answer : Add to your app module imports: ScrollDispatchModule . Add cdkScrollable to your mat-sidenav-content : <mat-sidenav-content cdkScrollable> </mat-sidenav-content> In your root component: a) inject ScrollDispatcher from @angular/cdk/overlay and subscribe to scrolling: constructor(public scroll: ScrollDispatcher) { this.scrollingSubscription = this.scroll .scrolled() .subscribe((data: CdkScrollable) => { this.onWindowScroll(data); }); } c) do something when scrolling, e.g. check the offset private onWindowScroll(data: CdkScrollable) { const scrollTop = data.getElementRef().nativeElement.scrollTop || 0; if (this.lastOffset > scrollTop) { // console.log('Show toolbar'); } else if (scrollTop < 10) { // console.log('Show toolbar'); } else if (scrollTop > 100) { // console.log('Hide toolbar'); } this.lastOffset = scrollTop; } D...

Angular: Conditional Class With *ngClass

Answer : Angular version 2+ provides several ways to add classes conditionally: type one [class.my-class]="step === 'step1'" type two [ngClass]="{'my-class': step === 'step1'}" and multiple option: [ngClass]="{'my-class': step === 'step1', 'my-class2':step === 'step2' }" type three [ngClass]="{1:'my-class1',2:'my-class2',3:'my-class4'}[step]" type four [ngClass]="(step=='step1')?'my-class1':'my-class2'" [ngClass]=... instead of *ngClass . * is only for the shorthand syntax for structural directives where you can for example use <div *ngFor="let item of items">{{item}}</div> instead of the longer equivalent version <template ngFor let-item [ngForOf]="items"> <div>{{item}}</div> </template> See also https://angular.io/docs/ts/latest/api/common/index/NgCl...