Friday, November 30, 2018

struggling to understand Injectors for the CDK modals of Angular 6

I tried to follow this and this to no avail. In the end I just decided to solve the problem my own way with some singleton state which holds an object like so:

import { President } from '../models/president.model';
import { OverlayRef } from '@angular/cdk/overlay';
export class ModalMetadata {
   overlayRef: OverlayRef;
   president: President;
   
   public closeAction(){
      if(this.overlayRef) {
         this.overlayRef.dispose();
         this.overlayRef = null;
      }
   }
}

 
 

My service is such:

import { Injectable, OnDestroy } from '@angular/core';
import { Overlay } from '@angular/cdk/overlay';
import { President } from '../models/president.model';
import { ModalMetadata } from '../models/modalMetadata.model';
import { ModalComponent } from '../layout/modal.component';
import { ComponentPortal } from '@angular/cdk/portal';
import { Router } from '@angular/router';
import { ISubscription } from 'rxjs/Subscription';
@Injectable()
export class ModalService {
   private backingStore: ModalMetadata;
   private subscription: ISubscription;
   
   constructor(private overlay: Overlay, private router: Router) {
      this.subscription = router.events.subscribe(()=> {
         if (this.backingStore) this.backingStore.closeAction();
      });
   }
   
   public open(president:President) {
      const filePreviewPortal = new ComponentPortal(ModalComponent);
      if (!this.backingStore) this.backingStore = new ModalMetadata();
      this.backingStore.president = president;
      if (!this.backingStore.overlayRef) {
         this.backingStore.overlayRef = this.overlay.create();
         this.backingStore.overlayRef.attach(filePreviewPortal);
      }
   }
   
   public getSingletonState():ModalMetadata {
      return this.backingStore;
   }
   
   ngOnDestroy(){
      this.subscription.unsubscribe();
   }
}

 
 

I have some inversion of control in TypeScript going on and thus there is a contract for the service. It looks like this:

import { President } from '../models/president.model';
import { ModalMetadata } from '../models/modalMetadata.model';
export class ModalContract {
   constructor() {}
   public open: (president:President) => void;
   public getSingletonState: () => ModalMetadata;
}

 
 

My component that I spit out in a modal looks like this:

import { Component, OnInit } from '@angular/core';
import { ModalMetadata } from '../models/modalMetadata.model';
import { ModalContract } from '../contracts/modal.contract';
@Component({
   selector: 'modal',
   templateUrl: './modal.component.html',
   styleUrls: ['./modal.component.css']
})
export class ModalComponent implements OnInit {
   private modalMetadata: ModalMetadata;
   
   constructor(public modalContract: ModalContract) {}
   
   ngOnInit() {
      this.modalMetadata = this.modalContract.getSingletonState();
   }
   
   close() {
      this.modalMetadata.closeAction();
   }
}

 
 

The template for the component is super simple. You will note that you may click an X to close to modal! Also you may have noticed above that the modal closes itself if you navigate away elsewhere.

{{ modalMetadata.president.Name}}... <a (click)="close()">X</a>

 
 

To use this stuff just call the open method in the service. This is all an better bake out of what I originally wrote about here.

 
 

Addendum 12/1/2018: I guess the "singleton state" isn't really a singleton as the state mutates. No... I spoke too soon. A singleton doesn't have to be constant. It's OK.

Set the emoji by your name to show you are at work in Slack.

  1. Click on your name at the upper left.
  2. Pick "Edit status..." from the menu that appears.
  3. Set an emoji and the text for the status by clicking on the existing settings.

Cash App allows for money transfers from mobile phones.

This has some details.

Tango Card

If you buy enough gift cards from a vendor in bulk odds are you can eventually get a price below the face value of the card if you are just buying enough. Tango Card has an interesting API for buying digital cards and assigning them on to others. You pay them face value and they do enough business to get a discount and thus not all of the money you give them gets passed along to the parties issuing the cards. This is how they make money. For average Joe developer trying to work with an API this is a good way to go as most other forums insist upon only indulging those who would buy in bulk brushing aside the business from small fish.

Thursday, November 29, 2018

.toBeTruthy() and .toBeFalsy()

These are legit Jasmine matchers.

required, optional, and query parameters in Angular routing

  1. This kinda touches on the distinction between paramMap and params.
  2. http://www.example.com/somethingerother;foo=13;bar=42;baz=69;qux=86 is an example of a URL with optional parameters and you'll note it is kinda like the usual get variables with the question marks and ampersands replaces by semicolons. (Query parameters have the usual question marks and ampersands per bullet 4 here.) The routerLink example here shows off optional parameters inside of the curly braces. Required parameters in contrast are those which make up URL chunks separated by forward slashes.
  3. <a [routerLink]="['/meh']" [preserveQueryParams]="true">meh</a> gives an example of preserving the query parameters when the paths change. You need the preserveQueryParams for the trick to work. The queryParamsHandling setting at bullet 8 here may go inline at the a tag I have here as well.
  4. Read queryParams off of the activatedRoute instance or the snapshot off of the activatedRoute instance as you would just params.

data-bound properties

In Angular, these imply Inputs at a selector tag.