mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-16 11:42:04 +08:00
support for custom components inside templates with tests
This commit is contained in:
@ -13,6 +13,10 @@ import observable = require("data/observable");
|
|||||||
import stackLayoutModule = require("ui/layouts/stack-layout");
|
import stackLayoutModule = require("ui/layouts/stack-layout");
|
||||||
import labelModule = require("ui/label");
|
import labelModule = require("ui/label");
|
||||||
import myCustomControlWithoutXml = require("./mymodule/MyControl");
|
import myCustomControlWithoutXml = require("./mymodule/MyControl");
|
||||||
|
import listViewModule = require("ui/list-view");
|
||||||
|
import frame = require("ui/frame");
|
||||||
|
import helper = require("../ui/helper");
|
||||||
|
import viewModule = require("ui/core/view");
|
||||||
|
|
||||||
export var test_load_IsDefined = function () {
|
export var test_load_IsDefined = function () {
|
||||||
TKUnit.assert(types.isFunction(builder.load), "ui/builder should have load method!");
|
TKUnit.assert(types.isFunction(builder.load), "ui/builder should have load method!");
|
||||||
@ -179,3 +183,31 @@ export var test_parse_ShouldParseCustomComponentWitXmlWithAttributes = function
|
|||||||
|
|
||||||
TKUnit.assert(panel.visibility === "collapsed", "Expected result: 'collapsed'; Actual result: " + panel.visibility);
|
TKUnit.assert(panel.visibility === "collapsed", "Expected result: 'collapsed'; Actual result: " + panel.visibility);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function test_parse_ShouldParseCustomComponentWithoutXmlInListViewTemplate() {
|
||||||
|
var p = <page.Page>builder.parse('<Page xmlns:customControls="xml-declaration/mymodule"><ListView items="{{ items }}" itemLoading="{{ itemLoading }}"><ListView.itemTemplate><customControls:MyControl /></ListView.itemTemplate></ListView></Page>');
|
||||||
|
|
||||||
|
function testAction(views: Array<viewModule.View>) {
|
||||||
|
var ctrl;
|
||||||
|
|
||||||
|
var obj = new observable.Observable();
|
||||||
|
obj.set("items", [1]);
|
||||||
|
obj.set("itemLoading", function (args: listViewModule.ItemEventData) {
|
||||||
|
ctrl = args.view
|
||||||
|
});
|
||||||
|
p.bindingContext = obj;
|
||||||
|
|
||||||
|
TKUnit.wait(0.2);
|
||||||
|
|
||||||
|
TKUnit.assert(ctrl instanceof myCustomControlWithoutXml.MyControl, "Expected result: custom control is defined!; Actual result: " + ctrl);
|
||||||
|
};
|
||||||
|
|
||||||
|
helper.navigate(function () { return p; });
|
||||||
|
|
||||||
|
try {
|
||||||
|
testAction([p.content, p]);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
helper.goBack();
|
||||||
|
}
|
||||||
|
}
|
@ -32,10 +32,10 @@ function parseInternal(value: string, exports: any): componentBuilder.ComponentM
|
|||||||
|
|
||||||
if (templateBuilder) {
|
if (templateBuilder) {
|
||||||
if (args.eventType === xml.ParserEventType.StartElement) {
|
if (args.eventType === xml.ParserEventType.StartElement) {
|
||||||
templateBuilder.addStartElement(args.elementName, args.attributes);
|
templateBuilder.addStartElement(args.prefix, args.namespace, args.elementName, args.attributes);
|
||||||
} else if (args.eventType === xml.ParserEventType.EndElement) {
|
} else if (args.eventType === xml.ParserEventType.EndElement) {
|
||||||
if (templateBuilder.elementName !== args.elementName) {
|
if (templateBuilder.elementName !== args.elementName) {
|
||||||
templateBuilder.addEndElement(args.elementName);
|
templateBuilder.addEndElement(args.prefix, args.elementName);
|
||||||
} else {
|
} else {
|
||||||
templateBuilder.build();
|
templateBuilder.build();
|
||||||
templateBuilder = undefined;
|
templateBuilder = undefined;
|
||||||
@ -72,35 +72,40 @@ function parseInternal(value: string, exports: any): componentBuilder.ComponentM
|
|||||||
|
|
||||||
var componentModule: componentBuilder.ComponentModule;
|
var componentModule: componentBuilder.ComponentModule;
|
||||||
|
|
||||||
if (args.namespace) {
|
if (args.prefix) {
|
||||||
// Custom components
|
// Custom components
|
||||||
var xmlPath = fs.path.join(fs.knownFolders.currentApp().path, args.namespace, args.elementName) + ".xml";
|
|
||||||
if (fs.File.exists(xmlPath)) {
|
|
||||||
// Custom components with XML
|
|
||||||
var jsPath = xmlPath.replace(".xml", ".js");
|
|
||||||
var subExports;
|
|
||||||
if (fs.File.exists(jsPath)) {
|
|
||||||
// Custom components with XML and code
|
|
||||||
subExports = require(jsPath.replace(".js", ""))
|
|
||||||
}
|
|
||||||
|
|
||||||
componentModule = loadInternal(xmlPath, subExports);
|
var ns = args.namespace;
|
||||||
|
|
||||||
// Attributes will be transfered to the custom component
|
if (ns) {
|
||||||
if (types.isDefined(componentModule) && types.isDefined(componentModule.component)) {
|
var xmlPath = fs.path.join(fs.knownFolders.currentApp().path, ns, args.elementName) + ".xml";
|
||||||
var attr: string;
|
|
||||||
for (attr in args.attributes) {
|
if (fs.File.exists(xmlPath)) {
|
||||||
componentBuilder.setPropertyValue(componentModule.component, subExports, exports, attr, args.attributes[attr]);
|
// Custom components with XML
|
||||||
|
var jsPath = xmlPath.replace(".xml", ".js");
|
||||||
|
var subExports;
|
||||||
|
if (fs.File.exists(jsPath)) {
|
||||||
|
// Custom components with XML and code
|
||||||
|
subExports = require(jsPath.replace(".js", ""))
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
componentModule = loadInternal(xmlPath, subExports);
|
||||||
// Custom components without XML
|
|
||||||
componentModule = componentBuilder.getComponentModule(args.elementName, args.namespace, args.attributes, exports);
|
// Attributes will be transfered to the custom component
|
||||||
|
if (types.isDefined(componentModule) && types.isDefined(componentModule.component)) {
|
||||||
|
var attr: string;
|
||||||
|
for (attr in args.attributes) {
|
||||||
|
componentBuilder.setPropertyValue(componentModule.component, subExports, exports, attr, args.attributes[attr]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Custom components without XML
|
||||||
|
componentModule = componentBuilder.getComponentModule(args.elementName, ns, args.attributes, exports);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Default components
|
// Default components
|
||||||
componentModule = componentBuilder.getComponentModule(args.elementName, args.namespace, args.attributes, exports);
|
componentModule = componentBuilder.getComponentModule(args.elementName, ns, args.attributes, exports);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (componentModule) {
|
if (componentModule) {
|
||||||
|
4
ui/builder/template-builder.d.ts
vendored
4
ui/builder/template-builder.d.ts
vendored
@ -6,8 +6,8 @@ declare module "ui/builder/template-builder" {
|
|||||||
constructor(templateProperty: TemplateProperty);
|
constructor(templateProperty: TemplateProperty);
|
||||||
|
|
||||||
elementName: string;
|
elementName: string;
|
||||||
addStartElement(elementName: string, attributes: Object);
|
addStartElement(prefix: string, namespace: string, elementName: string, attributes: Object);
|
||||||
addEndElement(elementName: string);
|
addEndElement(prefix: string, elementName: string);
|
||||||
build();
|
build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,12 +15,16 @@ export class TemplateBuilder {
|
|||||||
return this._templateProperty.elementName;
|
return this._templateProperty.elementName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public addStartElement(elementName: string, attributes: Object) {
|
public addStartElement(prefix: string, namespace: string, elementName: string, attributes: Object) {
|
||||||
this._items.push("<" + elementName + (attributes ? " " + getAttributesAsString(attributes) + ">" : ">"));
|
this._items.push("<" +
|
||||||
|
getElementNameWithPrefix(prefix, elementName) +
|
||||||
|
(namespace ? " " + getNamespace(prefix, namespace) : "") +
|
||||||
|
(attributes ? " " + getAttributesAsString(attributes) : "") +
|
||||||
|
">");
|
||||||
}
|
}
|
||||||
|
|
||||||
public addEndElement(elementName: string) {
|
public addEndElement(prefix: string, elementName: string) {
|
||||||
this._items.push("</" + elementName + ">");
|
this._items.push("</" + getElementNameWithPrefix(prefix, elementName) + ">");
|
||||||
}
|
}
|
||||||
|
|
||||||
public build() {
|
public build() {
|
||||||
@ -43,3 +47,11 @@ function getAttributesAsString(attributes: Object): string {
|
|||||||
|
|
||||||
return result.join(" ");
|
return result.join(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getElementNameWithPrefix(prefix: string, elementName: string): string {
|
||||||
|
return (prefix ? prefix + ":" : "") + elementName;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNamespace(prefix: string, namespace: string): string {
|
||||||
|
return 'xmlns:' + prefix + '="' + namespace + '"';
|
||||||
|
}
|
Reference in New Issue
Block a user