Posts

Showing posts with the label Typescript

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...

About "*.d.ts" In TypeScript

Answer : The "d.ts" file is used to provide typescript type information about an API that's written in JavaScript. The idea is that you're using something like jQuery or underscore, an existing javascript library. You want to consume those from your typescript code. Rather than rewriting jquery or underscore or whatever in typescript, you can instead write the d.ts file, which contains only the type annotations. Then from your typescript code you get the typescript benefits of static type checking while still using a pure JS library. d stands for Declaration Files: When a TypeScript script gets compiled there is an option to generate a declaration file (with the extension .d.ts) that functions as an interface to the components in the compiled JavaScript. In the process the compiler strips away all function and method bodies and preserves only the signatures of the types that are exported. The resulting declaration file can then be used to describ...

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

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: 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-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...

Can't Perform A React State Update On An Unmounted Component

Answer : Here is a React Hooks specific solution for Error Warning: Can't perform a React state update on an unmounted component. Solution You can declare let isMounted = true inside useEffect , which will be changed in the cleanup callback, as soon as the component is unmounted. Before state updates, you now check this variable conditionally: useEffect(() => { let isMounted = true; // note this flag denote mount status someAsyncOperation().then(data => { if (isMounted) setState(data); }) return () => { isMounted = false }; // use effect cleanup to set flag false, if unmounted }); const Parent = () => { const [mounted, setMounted] = useState(true); return ( <div> Parent: <button onClick={() => setMounted(!mounted)}> {mounted ? "Unmount" : "Mount"} Child </button> {mounted && <Child />} <p> Unmount Child, while it is still ...

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...

Correct Way Of Importing And Using Lodash In Angular

Answer : (if you care about tree shaking see update ) I suppose in order to bring lodash in to your project you already done npm install lodash --save npm install @types/lodash --save-dev If you want to import just required functions you should do: import * as debounce from 'lodash/debounce' or import { debounce } from "lodash"; Use it as: debounce() BTW: You might have to downgrade your typescript version to 2.0.10 as you are using angular 2.x. npm install typescript@2.0.10 --save-dev UPDATE: Recently I realised that lodash package is just not tree shakable, so if you need tree shaking just use lodash-es instead. npm install lodash-es --save npm install @types/lodash-es --save-dev import debounce from 'lodash-es/debounce' Importing lodash or any javascript library inside angular: step-1: Install the libarary(lodash) npm i --save lodash step-2: import it inside the component and use it. import it as follow: import 'lodash'; declare var _:any; o...

Angular 5 Remove Query Param

Answer : You can remove a query parameter by using the merge option of queryParamsHandling and passing in null for any params you wish to remove. // Remove query params this.router.navigate([], { queryParams: { 'yourParamName': null, 'youCanRemoveMultiple': null, }, queryParamsHandling: 'merge' }) This option is simpler and requires less work to ensure you are not removing other params. You also do not need to worry about cleaning up an observable subscription when your component is destroyed. UPDATE: @epelc's answer below is the up-to-date and correct way to do this: https://stackoverflow.com/a/52193044/5932590. Unfortunately, there is no clear-cut way to do this currently: https://github.com/angular/angular/issues/18011. However, as jasonaden commented on the linked thread, This could be done manually by merging the old and new query params, removing the key you don't want. Here is one way to do that: Let's say...

Can An Optional Parameter Be Null In TypeScript?

Answer : To answer my own question after trying... The types null and undefined are handled as separate types. The optional type is special, also allowing arguments to be left out of function calls. 1. Without a union or optional, nothing except the type itself is allowed. function foo(bar: string) { console.info(bar); } foo("Hello World!"); // OK foo(null); // Error foo(undefined); // Error foo() // Error 2. To additionally allow null , a union with null can be made. function foo(bar: string | null) { console.info(bar); } foo("Hello World!"); // OK foo(null); // OK foo(undefined); // Error foo() // Error 3. Allowing undefined works similarly. Note that the argument cannot be left out or null . function foo(bar: string | undefined) { console.info(bar); } foo("Hello World!"); // OK foo(null); // Error foo(undefined); // OK foo() // Error 4. You can also allow both, but the argument MUST still be given. function foo(b...

"Computed" Property In Typescript

Answer : If it's an interface then there's no syntax, because all properties in JavaScript can have getter/setter functions instead of being exposed fields. It's an implementation concern. BTW members in TypeScript use camelCase not TitleCase : export interface Person { // get + set: firstName: string; lastName : string; jobTitle : string; // get-only: readonly fullName : string; } class SimplePerson implements Person { public firstName: string; // value-property (“field”) public lastName: string; public jobTitle: string; get fullName(): string { // read-only property with getter function (this is not the same thing as a “function-property”) return this.firstName + " " + this.lastName; } } I note that it is confusing that TypeScript's designers chose to use the keyword readonly to denote "readable" properties in an interface when it doesn't actually prohibit an implementation from also havi...

A TypeScript GUID Class?

Answer : There is an implementation in my TypeScript utilities based on JavaScript GUID generators. Here is the code: class Guid { static newGuid() { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); return v.toString(16); }); } } // Example of a bunch of GUIDs for (var i = 0; i < 100; i++) { var id = Guid.newGuid(); console.log(id); } Please note the following: C# GUIDs are guaranteed to be unique. This solution is very likely to be unique. There is a huge gap between "very likely" and "guaranteed" and you don't want to fall through this gap. JavaScript-generated GUIDs are great to use as a temporary key that you use while waiting for a server to respond, but I wouldn't necessarily trust them as the primary key in a database. If you are going to rely on a JavaScript-generated GUID, I wo...

Angular 2 Get Current Route

Answer : Try this, import { Router } from '@angular/router'; export class MyComponent implements OnInit { constructor(private router:Router) { ... } ngOnInit() { let currentUrl = this.router.url; /// this will give you current url // your logic to know if its my home page. } } Try it import { Component } from '@angular/core'; import { Router, NavigationEnd } from '@angular/router'; @Component({...}) export class MyComponent { constructor(private router:Router) { router.events.subscribe(event => { if (event instanceof NavigationEnd ) { console.log("current url",event.url); // event.url has current url // your code will goes here } }); } } Try any of these from the native window object. console.log('URL:' + window.location.href); console.log('Path:' + window.location.pathname); console.log('Host:' + window.location.host); console.log('Ho...

Call An Overridden Method From Super Class In Typescript

Answer : The key is calling the parent's method using super.methodName(); class A { // A protected method protected doStuff() { alert("Called from A"); } // Expose the protected method as a public function public callDoStuff() { this.doStuff(); } } class B extends A { // Override the protected method protected doStuff() { // If we want we can still explicitly call the initial method super.doStuff(); alert("Called from B"); } } var a = new A(); a.callDoStuff(); // Will only alert "Called from A" var b = new B() b.callDoStuff(); // Will alert "Called from A" then "Called from B" Try it here The order of execution is: A 's constructor B 's constructor The assignment occurs in B 's constructor after A 's constructor— _super —has been called: function B() { _super.apply(this, arguments); // MyvirtualMethod c...

Angular: How To Download A File From HttpClient?

Answer : Blobs are returned with file type from backend. The following function will accept any file type and popup download window: downloadFile(route: string, filename: string = null): void{ const baseUrl = 'http://myserver/index.php/api'; const token = 'my JWT'; const headers = new HttpHeaders().set('authorization','Bearer '+token); this.http.get(baseUrl + route,{headers, responseType: 'blob' as 'json'}).subscribe( (response: any) =>{ let dataType = response.type; let binaryData = []; binaryData.push(response); let downloadLink = document.createElement('a'); downloadLink.href = window.URL.createObjectURL(new Blob(binaryData, {type: dataType})); if (filename) downloadLink.setAttribute('download', filename); document.body.appendChild(downloadLink); downloadLink.click(); }...

Cannot Import .tsx File From .ts File (and Vice Versa)

Answer : When you write import WriteEditor from './write_editor'; Webpack will automatically look for ./write_editor ./write_editor.js ./write_editor.json (And a few others) Since you're using .ts and .tsx , you need to tell it to look for those too in your Webpack config using resolve.extensions : { resolve: { extensions: [".js", ".json", ".ts", ".tsx"], }, } In my case, I got same error when using typescript-eslint . It is an app created by create-react-app . The way is by adding this code in .eslintrc.js . module.exports = { // ... settings: { 'import/resolver': { 'node': { 'extensions': ['.js','.jsx','.ts','.tsx'] } } } };

Cannot Find Module './in-memory-data-service' In Tour Of Heroes For Angular2

Answer : ng generate service InMemoryData --module=app Will create the src/app/in-memory-data.service.ts file. Then add the code listed in the tutorial and it will work. AFAIK they don't even imply that in the tutorial so don't feel bad. In fact what they say is The forRoot() configuration method takes an InMemoryDataService class that primes the in-memory database. The Tour of Heroes sample creates such a class src/app/in-memory-data.service.ts Which is gibberish and wrong. My projects created using current CLI Tools, and I installed this: npm install angular-in-memory-web-api --save It works for me. Just make sure all your bases are covered In your package.json , should match the one on this page. "angular-in-memory-web-api": "~0.1.1", Also, your systemjs.config file looks good too! In your app.module.ts , make sure that your in-memory-data-service import matches your file because in their example they have in-memory-data.service ...

Angular7 And NgbModal: How To Remove Default Auto Focus

Answer : The focus is needed to be within modal for accessibility and keyboard navigation reasons. By default the focus is on the first focusable element within modal, which in your case is the close button. You can add ngbAutofocus attribute to the element where you want the focus to be. Focus management demo. <button type="button" ngbAutofocus class="btn btn-danger" (click)="modal.close('Ok click')">Ok</button> You can read more on github If you don't mind the close button actually focused but want to get rid of the ugly outline, you can use outline: none . template.html : <button type="button" aria-label="Close">Close</button> styles.css : button[aria-label="Close"]:focus { outline: none; } It's an ugly hack, but you can add a non visible element as the first element: <input type="text" style="display:none" />