Giter Club home page Giter Club logo

ng-vdom's Issues

Feature: support on- prefix for event binding

Current Status

Only onEventName and on_eventName being supported, resulting in listener to eventName.

Expected

Support on-eventName as well which conforms to Angular template syntax.

Feature: directive support in render function

Integrate Directives with render function.

API Design

function directive(type: Type<any>): (value: any, extras?: object) => never
  • type: the directive class;
  • value: main input value for directive;
  • extras: additional input key value pairs in object;

Example

import { NgClass } from '@angular/common'
import { NgModel } from '@angular/forms'
import { directive, Renderable } from 'ng-renderable'

const ngClass = directive(NgClass)
const ngModel = directive(NgModel)

@Component()
class MyComponent extends Renderable {
  @Input() active: boolean
  value: string

  render() {
    const classNames = { highlight: this.active }

    return (
      <p ngClass={ ngClass(classNames) }>
        <input ngModel={ ngModel(this.value, { ngModelOptions: { /* ... */ } }) } onNgModelChange={ (value) => this.value = value } />
      </p>
    )
  }
}

Feature: project child to matched slot by selector

Current

All children are projected to default slot.

Expected

<p>Start</p>
<ng-content select="p"></ng-content>
<p>Middle</p>
<ng-content select="div"></ng-content>
<p>End</p>

Can be used with:

function render() {
  return (
    <MyComp>
      <p>Foo</p>
      <p ngProjectAs="div">Bar</p>
    </MyComp>
  )
}

Note:

  • Multiple children in same key will go to same slot with the original order;
  • Non-keyed children will still go to default slot (if there is);

Feature: TemplateRef rendering support

API Design

@Component({
  template: `
    <ng-template #myTemplate let-name>
      <p>Hello {{name}}!</p>
    </ng-template>
  `
})
class MyComp extends Renderable {
  @Input() name: string
  @ViewChild('myTemplate') myTemplate: TemplateRef<{ name: string }>

  render() {
    const MyTemplate = this.myTemplate

    return (
      <MyTemplate name={this.name} />
    )
  }
}

With helper directive:

import { RenderDef } from 'ng-render'

@Component({
  template: `
    <p *rnDef>Hello {{name}}!</p>
  `
})
class MyComp extends Renderable {
  @Input() name: string
  @ViewChild(RenderDef) rnDef: RenderDef<{ name: string }>

  render() {
    const MyTemplate = this.rnDef.template

    return (
      <MyTemplate name={this.name} />
    )
  }
}

Feature: option to render in sibling position

Current

Angular component always contains a host element, and Renderable always render content in child position.

Expected

Provide an option to render content in sibling position:

import { Renderable } from 'ng-renderable'

@Component({
  selector: 'my-comp'
})
class MyComponent extends Renderable {
  constructor(injector: Injector) {
    super(injector, { sibling: true })
  }

  render() {
    return <p>42</p>
  }
}

Resulting to:

<my-comp></my-comp>
<p>42</p>

Feature: separate inputs mode for template rendering

Current

@Component({
  template: `
    <render-outlet [def]="myDef"></render-outlet>
  `
})
class MyComp {
  myDef = <div className="foo">Foo</div>
}

Expected

@Component({
  template: `
    <render-outlet [type]="myType" [props]="{ className: 'foo' }">
      Foo
    </render-outlet>
  `
})
class MyComp {
  myType = 'div'
}

Feature: pipe support in render function

Integrate Pipes with render function.

API Design

function pipe(type: Type<any>): (value: any, ...extras: any[]) => never
  • type: the pipe class;
  • value: the value passed to pipe;
  • extras: additional parameters passed to pipe;

Example

import { AsyncPipe, DatePipe } from '@angular/common'
import { pipe, Renderable } from 'ng-renderable'

const async = pipe(AsyncPipe)
const date = pipe(DatePipe)

@Component()
class MyComponent extends Renderable {
  @Input() title: Observable<string>
  @Input() date: Date

  render() {
    return (
      <p title={ async(this.title) }>
        { date(this.date, 'fullDate') }
      </p>
    )
  }
}

Feature: support style- prefix for style binding

Expected

() => <p style-background-color={foo} style-font-size-px={bar}>

Should be equivalent to:

<p [style.background-color]="foo" [style.font-size.px]="bar">

Note: % is not valid in JSXAttributeName.

Feature: pipe to covert TemplateRef to function component

API Design

@Component({
  template: `
    <ng-template #dateCell let-date="date">{{ date | date:'yyyyMMdd' }}</ng-template>
    <bridged-comp [renderProp]="dateCell | renderable"></bridge-comp>
  `
})
class MyComp {}

Corresponding util function:

import { asRenderable, Renderable } from 'ng-render'

@Component({
  template: `
    <ng-template #dateCell let-date="date">{{ date | date:'yyyyMMdd' }}</ng-template>
  `
})
class MyComp extends Renderable {
  @ViewChild('dateCell') dateCell: TemplateRef<{ date: Date }>

  render() {
    return (
      <SomeComp renderProp={asRenderable(this.dateCell)}>
    )
  }
}

Feature: not use non-keyed tracking by default

Current

When not specifying key, all children are tracked by non-keyed way (index of type).

Expected

Should be keyed by default, element without key should always be consider replaced.

RFC: rename to ng-render

VDOM has severe problem in casing:

  • vdom/Vdom: incorrect;
  • vDom/VDom: weird for consecutive upper case;
  • VDOM/VDOM: ugly;

ng-render provides a more meaningful concepts, which integrates Angular with render function, also matches existing API:

import { Renderable } from 'ng-render'

@Component()
class MyComponent extends Renderable {
  render() { /* ... */ }
}

Directives:

  • VOutlet(v-outlet) -> RenderOutput(rn-outlet);

Feature: global bootstrap for browser rendering

Current

One can only mount elements in existing Angular component.

Expected

Support global bootstrap without any Angular code, like:

import { createElement, render } from 'ng-renderable'
import 'ng-renderable/browser'

render(<p>Hello World!</p>, document.querySelector('#main'))

Note: the only dependency should be @angular/core, not use @angular/platform-browser.

Feature: bridge existing class/function component to Angular

API Design

import { Migration } from 'ng-renderable'
import { Calendar } from 'some-lib'

@Directive({
  selector: 'my-calendar',
})
class CalendarComponent extends Migration<Calendar> {
  @Input() set date(value: Date) { this.update({ value }) }
  @Output() dateChange = this.observe(props => props.onChange)

  constructor(injector: Injector) {
    super(injector, Calendar)
  }
}

Note: to remain compatible with closure-compiler, string literals cannot be used.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.