Friday, November 29, 2019

Basic css class selector and tip

CSS Selector

#firstname
select element with id="firstname"

.myclass
select all elements with class="myclass"

p (or any html element tag)
select all <p> elements

AND (conditions without space, comma or any in between)
.class1.class2  
select all elements having both class1 and class2 class attribute
p.class1
select all p elements with class1 attribute

OR (comma separated conditions)
p, div
select all p and all div elements

descendant (space separated conditions)
div p
select all p element inside a <div> elements, child or grand child

direct child (> separated conditions)
div>p
select all p element whose direct parent is div

immediate sibling after
div+p
select p element that is immediately after a div element

general sibling after
div~p
select p element follows a p element, not necessary immediately


CSS debug tip
Chrome debugger provides few useful tools to work on css style.

1. element context menu:
After opening the chrome debugger, you can click on an html element, than then select "inspect" from the context menu, it will scroll to the selected element in Chrome debugger's Element view. From there, right click on the element, and the context menu will allow you to do many operation from chrome debugger, including: 
1. Edit the html element and attribute
2. Force the element state, such as focus, hover, visited, active
3. Set an auto break point when sub element has any change, or element's attribute has any change.

2. Style view menus
The Chrome debugger's style view has 3 menu items that can simplify the css style related debugging. 

:hov menu can be used to toggle the element state
.cls menu can be used to add or remove classes defined for the element
+ menu can be used to define new styles in a temporary css file file called inspector-stylesheet.css

Monday, November 11, 2019

Type declaration feature in TypeScript

Since ECMAScript 2015 (ECMAScript 6), javascript (typescript) begins to support class and interface, so it can share many common features as other common typed languages (C++, Java, Swift, etc), but there are still few syntax unique to typescript.

1. Property of constructor parameter
Usually, constructor parameter is just a function parameter, however, in typescript, if the constructor parameter has an accessory, like, private, public, or readonly, then it will automatically create a property for the class with the same parameter name and accessory. 
export class HttpComponent implements OnInit {
  loadedPosts = [];
  constructor(private http: HttpClient) { }


  onCreatePost(postData: Post) {
    console.log(postData);
    this.http.post('https://restapitest-d6f8c.firebaseio.com/posts.json', postData)
      .subscribe(responseData => {
        console.log(responseData);
      });
  }
}

2. interface for defining function type
Interface can be used to define a function type as below
type MyFunc = (key: number, value: string) => void;
export class HttpComponent implements OnInit {
  loadedPosts = [];
  myfunc: MyFunc;
  constructor(private http: HttpClient) {
    this.myfunc = (n: number, v: string) => {
      console.log(v + ': ' + n);
    };
   }
  onTest() {
    this.myfunc(5, 'my number is');
  }
}
3. indexable type for collection 
Interface can describe collection data type using index, which means the data collection can be indexed using the key of specified type. The name of key does not matter.
For array collection, the index is number type, and can be represented as below:
export interface Strings {
    [index: number]: string;
}
onTest() {
    const s: Strings = ['abc', 'def'];
    const s1 = s[0];
    console.log(s1);
}

For dictionary (i.e. object) collection,the index is the key type in key-value pairs as shown below.
export interface Post {
    title: string;
    content: string;
    id?: string;
}

export interface Posts {
    [id: string]: Post;
}

  onFetchPosts() {
    this.http.get('https://restapitest-d6f8c.firebaseio.com/posts.json')
      .pipe( map( (responseData: Posts) => {
        const postArray: Post[] = [];
        for (const key in responseData) {
          if (responseData.hasOwnProperty(key)) {
            postArray.push({... responseData[key], id: key});
          }
        }
        return postArray;
      })).subscribe(posts => {
        console.log(posts[0].title, posts[0].content);
      });
  }
}

The interface type definition can be used anonymously as below without explicitly defining an interface for it.
 onFetchPosts() {
    this.http.get('https://restapitest-d6f8c.firebaseio.com/posts.json')
      .pipe( map( (responseData: {[id: string]: Post}) => {
        const postArray: Post[] = [];
        for (const key in responseData) {
          if (responseData.hasOwnProperty(key)) {
            postArray.push({... responseData[key], id: key});
          }
        }
        return postArray;
      })).subscribe(posts => {
        console.log(posts[0].title, posts[0].content);
      });
  }
}
|

Friday, November 8, 2019

RxJs Operator and Pipe for Angular

Operator in RxJS refers to several helper operation (map, filter, etc) used for processing input values emitted by an observable, and the output is a new observable with updated values. The input observable is not changed.

For example, the below method shows how an input observable gets processed and transformed into an output observable
function multiplyByTen(input) { var output = Rx.Observable.create(function subscribe(observer) { input.subscribe({ next: (v) => observer.next(10 * v), error: (err) => observer.error(err), complete: () => observer.complete() }); }); return output; } var input = Rx.Observable.from([1, 2, 3, 4]); var output = multiplyByTen(input); output.subscribe(x => console.log(x));


In the above code, the only thing may changed is how each data item will be handled in subscriber's next method, that is really how operator defines its function. In operator's map function, it defines how old data items are transformed into output observable's new data time as below :
    const nums = of(1, 2, 3);
    const squareValues = map(
        (val: number) => val * val
    );

    let obs: Observable<number> = squareValues(nums);
    obs.subscribe( v => {
      console.log(v);
    });
Similarly, the filter operator can be applied to an observable as below
    const odd = filter((n: number, ind: number) => {
      console.log('number ', ind, ' = ', n);
      return n % 2 === 0;
    });
    obs = odd(nums);
    obs.subscribe( v => {
      console.log(v);
    });

Essentially, the RxJs operator is a function that takes an input transform function as parameter, and returns a new function, which takes an observable as input parameter, and output a new observable as return value. Each value emitted from the input observable will be transformed or filtered by the transform handler, and then emitted to the output observable.
Multiple RxJs operators can also be piped together. Note, the RxJs pipe has nothing to do with angular string interpolation's pipe operation (|), and they just happen to have the same name.
The below is an example of using pipe
    const squareOddVals = pipe(
      filter((n: number) => n % 2 !== 0),
      map(n => n * n)
    );
    const squareOdd = squareOddVals(nums);
    squareOdd.subscribe( x => {
      console.log(x);
    });

Note, pipe is also a method of RxJS observable object, so it can be called directly on observable object as below
    const sqEven = of(1, 2, 3, 4, 5, 6)
      .pipe(
        filter((n: number) => n %2 === 0),
        map(n => n * n)
      ).subscribe( x =>
        console.log(x)
      );
Pipe has another important usage is flattening the embedded subscribe calls with exhaustMap, switchMap, concatMap and mergeMap.