The Template Pipeline Continued...

Matias & Alex

Styling in the template pipeline

  • [style.prop]
  • [style]
  • [class.name]
  • [class]

How are the instructions generated?


<div
  [style.width]="myWidth"
  [class.active]=
     "myActiveClass"
  [style]="myStyles"
  [class]="myClasses">
  ...
</div>
if (rf & 1) {
  element(0, 'div');
}
if (rf & 2) {
  styleProp('width',
            ctx.myWidth);
  classProp('active',
            ctx.myActiveClass);
  styleMap(ctx.myStyles);
  classMap(ctx.myClasses);
}
  • Template is parsed into an AST
  • Properties are extracted from the AST
  • Properties are upgraded into style and class bindings

What is going on here?


<div
  [style.width]="myWidth"
  [class.active]=
     "myActiveClass"
  [style]="myStyles"
  [class]="myClasses">
  ...
</div>

// create
ElementNode,  // <div>

// update  
PropertyNode, // style.width
PropertyNode, // class.active
PropertyNode, // style
PropertyName  // class

// [style.width]
property = {
  kind: NodeKind.Property,
  name: 'style.width',
  expression: o.Expression,
}
  • Nodes are useless on their own
  • They need to be converted into ivy instructions
  • Nodes are passed into emitters

Nodes => Ivy Instructions

interface CreateEmitter {    
  emit(node: CreateNode):
    o.Statement|null;
}

interface UpdateEmitter {
  emit(node: UpdateNode):
    o.Statement|null;
}
  • [style], [style.prop], [class] and [class.name] are tread as properties
  • How do we get the pipeline to special case them for styling?

But these are just properties


// [style.width]
property = {
  kind: NodeKind.Property,
  name: 'style.width',
  expression: o.Expression,
}

// [style.width]
property = {
  kind: NodeKind.StyleProp,
  name: 'width',
  expression: o.Expression,
}
  • Stages modify the set of nodes in the update list into different nodes
  • StyleBindingStage
  • ClassBindingStage

Style and Class
Property Stages

export class StyleTransform
  implements Transform {
    
  visit(node: Node, list: List): Node {
    // [style] or [style.prop]
    if (node.kind === NodeKind.Property
        && isStyleProp(node.name)) { 
      node = updateToStyleBinding(node);
    }
    
    return node;
  }
}
function updateToStyleBinding(
  node: PropertyNode) {
    
  if (node.name === 'style') {
    return {...} as StyleMap;
  } else {
    return {...} as StyleProp;
  }
}
property = {
  kind: NodeKind.StyleProp,
  name: 'propName', // width
  expression: o.Expression,
}

property = {
  kind: NodeKind.StyleMap,
  expression: o.Expression,
}
property = {
  kind: NodeKind.ClassProp,
  name: 'className', // activeClass
  expression: o.Expression,
}

property = {
  kind: NodeKind.ClassMap,
  expression: o.Expression,
}

Our Pair Programming Process

Tuesday

  • We always code
  • Pairing together over GVC
  • VSCode + LiveShare
  • Planning and pseudocode'ing
  • High-level discussions over API and usecases

Thursday

TL: Jan

  • Initial discussions
  • High-level talk of data-structures
  • Whiteboarding
  • Element creation and prototyping
  • Plans to get pieces of template.ts into the pipeline

TL: Feb

Positives

  • Great feedback
  • API iteration
  • Simple code structures
  • Knowledge share
  • Difficult to land things into angular/angular in an intermediate state

Negatives

  • Fun experience working on the compiler and spending time designing
  • Pleasure to work with Alex :)

Feedback from Matias

Thank you!

The Template Pipeline Continued...

By Matias Niemelä

The Template Pipeline Continued...

  • 191