Giter VIP home page Giter VIP logo

ng-vdom's Introduction

NG-VDOM

Virtual DOM extension for Angular, heavily inspired by Inferno.

Installation

Install from NPM or Yarn:

npm install ng-vdom --save

Add to NgModule imports:

import { VDomModule } from 'ng-vdom';

@NgModule({
  imports: [
    VDomModule
  ]
})
export class SomeModule {}

Edit tsconfig JSX options:

{
  "compilerOptions": {
    "jsx": "react",
    "jsxFactory": "createElement"
  }
}

Usage

Online Demo.

Make an Angular Component extends Renderable with a render method:

import { Component } from '@angular/core'
import { createElement, Renderable } from 'ng-vdom'

@Component({
  template: ``
})
export class AppComponent extends Renderable {
  render() {
    return (
      <h1>Hello World!</h1>
    )
  }
}

Embedding Virtual DOM contents inside template

import { Component, NgModule } from '@angular/core'
import { VDomModule } from 'ng-vdom'

@Component({
  template: `
    <v-outlet [def]="element"></v-outlet>
  `
})
export class AppComponent {
  element = <h1>Hello World</h1>
}

@NgModule({
  imports: [ VDomModule ],
})
export class AppModule { }

What can be rendered?

  • Intrinsic elements (DOM element in browser);
  • Class component (not fully react compatible);
  • Function component;
  • Angular component (need to be in entryComponents);

Roadmap

  • Global boostrap without Angular code;
  • Fragment render support;
  • Array render support;
  • React-compatible class component support;
  • HTML Attribute support;

ng-vdom's People

Contributors

layzeedk avatar trotyl avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ng-vdom's Issues

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

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

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: 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>
    )
  }
}

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.