diff --git a/.ctags-exclude b/.ctags-exclude index cd8ec8e08..6e7c9dcf0 100644 --- a/.ctags-exclude +++ b/.ctags-exclude @@ -26,3 +26,4 @@ src/angular2 web/*.js src/*.js deps/angular/dist +deps/angular/tmp diff --git a/ng-sample/app/app.css b/ng-sample/app/app.css index 17e1cb37f..bf8e9bd0e 100644 --- a/ng-sample/app/app.css +++ b/ng-sample/app/app.css @@ -14,6 +14,6 @@ } button { - font-size: 42; + font-size: 20; horizontal-align: center; } diff --git a/ng-sample/app/renderer-test.ts b/ng-sample/app/renderer-test.ts index b02729d32..318b49e03 100644 --- a/ng-sample/app/renderer-test.ts +++ b/ng-sample/app/renderer-test.ts @@ -1,42 +1,45 @@ -import {Inject, Component, View} from 'angular2/core'; +import {Component, Directive, Host, ElementRef, Input} from 'angular2/core'; @Component({ selector: 'templated-component', + directives: [TemplatedComponent], templateUrl: 'title.html' }) export class TemplatedComponent { + @Input() public renderChild: boolean = false; + @Input() public text: string = "Hello, external templates"; +} + +@Directive({ + selector: 'Progress', +}) +export class ProgressComponent { + constructor(private element: ElementRef) { + } + + ngOnInit() { + this.element.nativeElement.value = 90; + } } @Component({ selector: 'renderer-test', - directives: [TemplatedComponent], + directives: [TemplatedComponent, ProgressComponent], template: ` - - - - - - - - - - - - - - - - + + + + + + + + + + - - - - - - - - - + + + `, }) export class RendererTest { @@ -54,9 +57,8 @@ export class RendererTest { this.moreDetailsText = 'More details:'; this.detailLines = [ - "ngFor inside a ngIf", - "Street address", - "Country, city", + "ngFor inside a ngIf 1", + "ngFor inside a ngIf 2", ]; } diff --git a/ng-sample/app/title.html b/ng-sample/app/title.html index 235ab44fa..c7537fac5 100644 --- a/ng-sample/app/title.html +++ b/ng-sample/app/title.html @@ -1 +1,2 @@ - + + diff --git a/ng-sample/tsconfig.json b/ng-sample/tsconfig.json index f3b8d24ad..66fb9f9eb 100644 --- a/ng-sample/tsconfig.json +++ b/ng-sample/tsconfig.json @@ -35,5 +35,9 @@ "filesGlob": [ "node_modules/tns-core-modules/tns-core-modules.d.ts", "app/**/*.ts" + ], + "exclude": [ + "node_modules", + "platforms" ] } \ No newline at end of file diff --git a/package.json b/package.json index b357b5552..aca19ff69 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ }, "scripts": {}, "dependencies": { - "angular2": "2.0.0-beta.0", + "angular2": "2.0.0-beta.1", "parse5": "1.4.2", "punycode": "1.3.2", "querystring": "0.2.0", diff --git a/src/nativescript-angular/application.ts b/src/nativescript-angular/application.ts index 293a566d0..90427298d 100644 --- a/src/nativescript-angular/application.ts +++ b/src/nativescript-angular/application.ts @@ -13,8 +13,8 @@ import {platform, ComponentRef, PLATFORM_DIRECTIVES, PLATFORM_PIPES} from 'angul import {bind, provide, Provider} from 'angular2/src/core/di'; import {DOM} from 'angular2/src/platform/dom/dom_adapter'; -import {Renderer} from 'angular2/src/core/render/api'; -import {NativeScriptRenderer} from './renderer'; +import {RootRenderer, Renderer} from 'angular2/src/core/render/api'; +import {NativeScriptRootRenderer, NativeScriptRenderer} from './renderer'; import {NativeScriptDomAdapter} from './dom_adapter'; import {XHR} from 'angular2/src/compiler/xhr'; import {FileSystemXHR} from './xhr'; @@ -34,6 +34,8 @@ export function nativeScriptBootstrap(appComponentType: any, NativeScriptDomAdapter.makeCurrent(); let nativeScriptProviders: ProviderArray = [ + NativeScriptRootRenderer, + provide(RootRenderer, {useClass: NativeScriptRootRenderer}), NativeScriptRenderer, provide(Renderer, {useClass: NativeScriptRenderer}), provide(XHR, {useClass: FileSystemXHR}), diff --git a/src/nativescript-angular/renderer.ts b/src/nativescript-angular/renderer.ts index 668e7d076..e7bdb1baf 100644 --- a/src/nativescript-angular/renderer.ts +++ b/src/nativescript-angular/renderer.ts @@ -1,261 +1,160 @@ import {Inject, Injectable} from 'angular2/src/core/di'; -import {RenderComponentTemplate} from 'angular2/src/core/render/api'; -import {createRenderView, NodeFactory} from 'angular2/src/core/render/view_factory'; import { Renderer, - RenderEventDispatcher, - RenderElementRef, - RenderProtoViewRef, - RenderViewRef, - RenderFragmentRef, - RenderViewWithFragments, - RenderTemplateCmd + RootRenderer, + RenderComponentType } from 'angular2/src/core/render/api'; import {isBlank} from 'angular2/src/facade/lang'; -import { - DefaultProtoViewRef, - DefaultRenderView, - DefaultRenderFragmentRef -} from 'angular2/src/core/render/view'; import {DOM} from 'angular2/src/platform/dom/dom_adapter'; -import {ViewNode, DummyViewNode} from './view_node'; +import {View} from "ui/core/view"; +import {topmost} from 'ui/frame'; +import * as util from "./view-util"; //var console = {log: function(msg) {}} @Injectable() -export class NativeScriptRenderer extends Renderer implements NodeFactory { - constructor() { +export class NativeScriptRootRenderer extends RootRenderer { + private _registeredComponents: Map = new Map(); + + renderComponent(componentProto: RenderComponentType): Renderer { + var renderer = this._registeredComponents.get(componentProto.id); + if (isBlank(renderer)) { + renderer = new NativeScriptRenderer(this, componentProto); + this._registeredComponents.set(componentProto.id, renderer); + } + return renderer; + } +} + +@Injectable() +export class NativeScriptRenderer extends Renderer { + constructor(private _rootRenderer: NativeScriptRootRenderer, private componentProto: RenderComponentType) { super(); console.log('NativeScriptRenderer created'); } - public createProtoView(componentTemplateId: string, cmds: RenderTemplateCmd[]): RenderProtoViewRef { - console.log('NativeScriptRenderer.createProtoView: ' + componentTemplateId + ' -> ' + cmds); - return new DefaultProtoViewRef(this._componentTemplates.get(componentTemplateId), cmds); + renderComponent(componentProto: RenderComponentType): Renderer { + return this._rootRenderer.renderComponent(componentProto); } - public createRootHostView( - hostProtoViewRef: RenderProtoViewRef, - fragmentCount: number, - hostElementSelector: string - ): RenderViewWithFragments { - console.log("NativeScriptRenderer.createRootHostView"); - - let rootViewWithFragments = this._createView(hostProtoViewRef, null); - - let rootView = resolveInternalDomView(rootViewWithFragments.viewRef); - let rootNode = rootView.boundElements[0]; - rootNode.attachToView(); - - return rootViewWithFragments; + selectRootElement(selector: string): util.NgView { + console.log('ROOT'); + const page = topmost().currentPage; + page.nodeName = 'Page'; + return page; } - public createView(protoViewRef: RenderProtoViewRef, fragmentCount: number): RenderViewWithFragments { - console.log("NativeScriptRenderer.createView"); - return this._createView(protoViewRef, null); + createViewRoot(hostElement: util.NgView): util.NgView { + console.log('CREATE VIEW ROOT: ' + hostElement.nodeName); + return hostElement; } - private _createView(protoViewRef: RenderProtoViewRef, inplaceElement: HTMLElement): RenderViewWithFragments { - var dpvr = protoViewRef; - var view = createRenderView(dpvr.template, dpvr.cmds, inplaceElement, this); - return new RenderViewWithFragments(view, view.fragments); + projectNodes(parentElement: util.NgView, nodes: util.NgView[]): void { + console.log('NativeScriptRenderer.projectNodes'); + nodes.forEach((node) => { + util.insertChild(parentElement, node); + }); } - public destroyView(viewRef: RenderViewRef) { - console.log("NativeScriptRenderer.destroyView"); - // Seems to be called on component dispose only (router outlet) - //TODO: handle this when we resolve routing and navigation. - } + attachViewAfter(anchorNode: util.NgView, viewRootNodes: util.NgView[]) { + console.log('NativeScriptRenderer.attachViewAfter: ' + anchorNode.nodeName + ' ' + anchorNode); + const parent = anchorNode.parent; + const insertPosition = util.getChildIndex(parent, anchorNode); - public getRootNodes(fragment: RenderFragmentRef): ViewNode[] { - return resolveInternalDomFragment(fragment); + viewRootNodes.forEach((node, index) => { + const childIndex = insertPosition + index + 1; + util.insertChild(parent, node, childIndex); + this.animateNodeEnter(node); + }); } - public attachFragmentAfterFragment(previousFragmentRef: RenderFragmentRef, fragmentRef: RenderFragmentRef) { - console.log("NativeScriptRenderer.attachFragmentAfterFragment"); - - var previousFragmentNodes = resolveInternalDomFragment(previousFragmentRef); - if (previousFragmentNodes.length > 0) { - var sibling = previousFragmentNodes[previousFragmentNodes.length - 1]; - let nodes = resolveInternalDomFragment(fragmentRef); - this.attachFragmentAfter(sibling, nodes); + detachView(viewRootNodes: util.NgView[]) { + console.log('NativeScriptRenderer.detachView'); + for (var i = 0; i < viewRootNodes.length; i++) { + var node = viewRootNodes[i]; + util.removeChild(node.parent, node); + this.animateNodeLeave(node); } } - public attachFragmentAfterElement(location: RenderElementRef, fragmentRef: RenderFragmentRef) { - console.log("NativeScriptRenderer.attachFragmentAfterElement"); - - let element = resolveBoundNode(location); - let nodes = resolveInternalDomFragment(fragmentRef); - this.attachFragmentAfter(element, nodes); - } - - private attachFragmentAfter(anchorNode: ViewNode, fragmentNodes: ViewNode[]) { - var startIndex = anchorNode.parentNode.getChildIndex(anchorNode) + 1; - - fragmentNodes.forEach((node, index) => { - console.log('attachFragmentAfter: child: ' + node.viewName + ' after: ' + anchorNode.viewName + ' startIndex: ' + startIndex + ' index: ' + index); - anchorNode.parentNode.insertChildAt(startIndex + index, node); - node.attachToView(startIndex + index); - }); - } - - detachFragment(fragmentRef: RenderFragmentRef) { - console.log('NativeScriptRenderer.detachFragment'); - - var fragmentNodes = resolveInternalDomFragment(fragmentRef); - fragmentNodes.forEach((node) => { - console.log('detaching fragment child: ' + node.viewName); - if (node.parentNode) - node.parentNode.removeChild(node); - }); + animateNodeEnter(node: util.NgView) { } - hydrateView(viewRef: RenderViewRef) { - console.log("NativeScriptRenderer.hydrateView "); - //DOING nothing -- the view init code happens on attach: ViewNode#createUI + animateNodeLeave(node: util.NgView) { } - dehydrateView(viewRef: RenderViewRef) { - console.log("NativeScriptRenderer.dehydrateView"); - //TODO: detach events + public destroyView(hostElement: util.NgView, viewAllNodes: util.NgView[]) { + console.log("NativeScriptRenderer.destroyView"); + // Seems to be called on component dispose only (router outlet) + //TODO: handle this when we resolve routing and navigation. } - setElementProperty(location: RenderElementRef, propertyName: string, propertyValue: any) { - console.log("NativeScriptRenderer.setElementProperty " + propertyName + " = " + propertyValue); - - let node = resolveBoundNode(location); - node.setProperty(propertyName, propertyValue); + setElementProperty(renderElement: util.NgView, propertyName: string, propertyValue: any) { + console.log("NativeScriptRenderer.setElementProperty " + renderElement.nodeName + ': ' + propertyName + " = " + propertyValue); + util.setProperty(renderElement, propertyName, propertyValue); } - setElementAttribute(location: RenderElementRef, attributeName: string, attributeValue: string) { - console.log("NativeScriptRenderer.setElementAttribute " + attributeName + " = " + attributeValue); - return this.setElementProperty(location, attributeName, attributeValue); + setElementAttribute(renderElement: util.NgView, attributeName: string, attributeValue: string) { + console.log("NativeScriptRenderer.setElementAttribute " + renderElement.nodeName + ': ' + attributeName + " = " + attributeValue); + return this.setElementProperty(renderElement, attributeName, attributeValue); } - setElementClass(location: RenderElementRef, className: string, isAdd: boolean): void { + setElementClass(renderElement: util.NgView, className: string, isAdd: boolean): void { console.log("NativeScriptRenderer.setElementClass " + className + " - " + isAdd); - let node = resolveBoundNode(location); if (isAdd) { - node.addClass(className); + util.addClass(renderElement, className); } else { - node.removeClass(className); + util.removeClass(renderElement, className); } } - setElementStyle(location: RenderElementRef, styleName: string, styleValue: string): void { - let node = resolveBoundNode(location); - node.setStyleProperty(styleName, styleValue); + setElementStyle(renderElement: util.NgView, styleName: string, styleValue: string): void { + util.setStyleProperty(renderElement, styleName, styleValue); } /** * Used only in debug mode to serialize property changes to comment nodes, * such as