mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-16 03:31:45 +08:00
Added application resources (used for binding converters), also some bug
fixes (binding related).
This commit is contained in:
@ -6,6 +6,8 @@ import styleScope = require("ui/styling/style-scope");
|
|||||||
|
|
||||||
export var cssFile: string = "app.css"
|
export var cssFile: string = "app.css"
|
||||||
|
|
||||||
|
export var resources: any = {};
|
||||||
|
|
||||||
export var onUncaughtError: (error: definition.NativeScriptError) => void = undefined;
|
export var onUncaughtError: (error: definition.NativeScriptError) => void = undefined;
|
||||||
|
|
||||||
export var onLaunch: (context: any) => any = undefined;
|
export var onLaunch: (context: any) => any = undefined;
|
||||||
|
5
application/application.d.ts
vendored
5
application/application.d.ts
vendored
@ -23,6 +23,11 @@ declare module "application" {
|
|||||||
*/
|
*/
|
||||||
export var mainModule: string;
|
export var mainModule: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An application level static resources.
|
||||||
|
*/
|
||||||
|
export var resources: any;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The application level css file name (starting from the application root). Used to set css across all pages.
|
* The application level css file name (starting from the application root). Used to set css across all pages.
|
||||||
* Css will be applied for every page and page css will be applied after.
|
* Css will be applied for every page and page css will be applied after.
|
||||||
|
@ -429,6 +429,38 @@ export function test_loadMoreItems_not_raised_when_showing_many_items() {
|
|||||||
helper.buildUIAndRunTest(listView, testAction);
|
helper.buildUIAndRunTest(listView, testAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function test_usingAppLevelConvertersInListViewItems() {
|
||||||
|
var listView = new listViewModule.ListView();
|
||||||
|
|
||||||
|
var dateConverter = function (value, format) {
|
||||||
|
var result = format;
|
||||||
|
var day = value.getDate();
|
||||||
|
result = result.replace("DD", month < 10 ? "0" + day : day);
|
||||||
|
var month = value.getMonth() + 1;
|
||||||
|
result = result.replace("MM", month < 10 ? "0" + month : month);
|
||||||
|
result = result.replace("YYYY", value.getFullYear());
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
app.resources["dateConverter"] = dateConverter;
|
||||||
|
|
||||||
|
var data = new observableArray.ObservableArray();
|
||||||
|
|
||||||
|
data.push({date: new Date()});
|
||||||
|
|
||||||
|
function testAction(views: Array<viewModule.View>) {
|
||||||
|
listView.itemTemplate = "<Label id=\"testLabel\" text=\"{{ date, date | dateConverter('DD.MM.YYYY') }}\" />";
|
||||||
|
listView.items = data;
|
||||||
|
|
||||||
|
TKUnit.wait(ASYNC);
|
||||||
|
var nativeElementText = getTextFromNativeElementAt(listView, 0);
|
||||||
|
|
||||||
|
TKUnit.assertEqual(nativeElementText, dateConverter(new Date(), "DD.MM.YYYY"), "native element");
|
||||||
|
};
|
||||||
|
|
||||||
|
helper.buildUIAndRunTest(listView, testAction);
|
||||||
|
}
|
||||||
|
|
||||||
function loadViewWithItemNumber(args: listViewModule.ItemEventData) {
|
function loadViewWithItemNumber(args: listViewModule.ItemEventData) {
|
||||||
if (!args.view) {
|
if (!args.view) {
|
||||||
args.view = new labelModule.Label();
|
args.view = new labelModule.Label();
|
||||||
@ -436,6 +468,19 @@ function loadViewWithItemNumber(args: listViewModule.ItemEventData) {
|
|||||||
(<labelModule.Label>args.view).text = "item " + args.index;
|
(<labelModule.Label>args.view).text = "item " + args.index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getTextFromNativeElementAt(listView: listViewModule.ListView, index: number): any {
|
||||||
|
if (listView.android) {
|
||||||
|
var nativeElement = listView.android.getChildAt(index);
|
||||||
|
if (nativeElement instanceof android.view.ViewGroup) {
|
||||||
|
return (<android.widget.TextView>(<any>nativeElement.getChildAt(0))).getText();
|
||||||
|
}
|
||||||
|
return (<android.widget.TextView>nativeElement).getText();
|
||||||
|
}
|
||||||
|
else if (listView.ios) {
|
||||||
|
return listView.ios.visibleCells()[index].contentView.subviews[0].text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function getNativeViewCount(listView: listViewModule.ListView): number {
|
function getNativeViewCount(listView: listViewModule.ListView): number {
|
||||||
if (listView.android) {
|
if (listView.android) {
|
||||||
return listView.android.getChildCount();
|
return listView.android.getChildCount();
|
||||||
|
@ -8,6 +8,7 @@ import frameModule = require("ui/frame");
|
|||||||
import pageModule = require("ui/page");
|
import pageModule = require("ui/page");
|
||||||
import listViewModule = require("ui/list-view");
|
import listViewModule = require("ui/list-view");
|
||||||
import buttonModule = require("ui/button");
|
import buttonModule = require("ui/button");
|
||||||
|
import observable = require("data/observable");
|
||||||
|
|
||||||
// <snippet module="ui/tab-view" title="TabView">
|
// <snippet module="ui/tab-view" title="TabView">
|
||||||
// # TabView
|
// # TabView
|
||||||
@ -38,6 +39,8 @@ import tabViewModule = require("ui/tab-view");
|
|||||||
// ```
|
// ```
|
||||||
// </snippet>
|
// </snippet>
|
||||||
|
|
||||||
|
var ASYNC = 0.3;
|
||||||
|
|
||||||
function _createTabView(): tabViewModule.TabView {
|
function _createTabView(): tabViewModule.TabView {
|
||||||
// <snippet module="ui/tab-view" title="TabView">
|
// <snippet module="ui/tab-view" title="TabView">
|
||||||
// ## Creating a TabView
|
// ## Creating a TabView
|
||||||
@ -367,6 +370,44 @@ export var testWhenNavigatingBackToANonCachedPageContainingATabViewWithAListView
|
|||||||
TKUnit.assert(listView !== undefined, "ListView should be created when navigating back to the main page.");
|
TKUnit.assert(listView !== undefined, "ListView should be created when navigating back to the main page.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function testBindingIsRefreshedWhenTabViewItemIsUnselectedAndThenSelectedAgain() {
|
||||||
|
helper.buildUIAndRunTest(_createTabView(), function (views: Array<viewModule.View>) {
|
||||||
|
var viewModel = new observable.Observable();
|
||||||
|
viewModel.set("counter", 0);
|
||||||
|
frameModule.topmost().currentPage.bindingContext = viewModel;
|
||||||
|
|
||||||
|
var tabView = <tabViewModule.TabView>views[0];
|
||||||
|
|
||||||
|
var items = _createItems(10);
|
||||||
|
|
||||||
|
var StackLayout0 = new stackLayoutModule.StackLayout();
|
||||||
|
var label0 = new labelModule.Label();
|
||||||
|
label0.text = "Tab 0";
|
||||||
|
label0.id = "testLabel";
|
||||||
|
label0.bind({ sourceProperty: "counter", targetProperty: "text", twoWay: true });
|
||||||
|
StackLayout0.addChild(label0);
|
||||||
|
var tabEntry0 = {
|
||||||
|
title: "Tab 0",
|
||||||
|
view: StackLayout0
|
||||||
|
};
|
||||||
|
items.push(tabEntry0);
|
||||||
|
tabView.items = items;
|
||||||
|
|
||||||
|
tabView.selectedIndex = 10;
|
||||||
|
TKUnit.wait(ASYNC);
|
||||||
|
|
||||||
|
tabView.selectedIndex = 0;
|
||||||
|
TKUnit.wait(ASYNC);
|
||||||
|
|
||||||
|
tabView.selectedIndex = 10;
|
||||||
|
TKUnit.wait(ASYNC);
|
||||||
|
var expectedValue = 5;
|
||||||
|
viewModel.set("counter", expectedValue);
|
||||||
|
var testLabel = <labelModule.Label>(tabView.items[10].view.getViewById("testLabel"))
|
||||||
|
TKUnit.assertEqual(testLabel.text, expectedValue, "binding is not working!");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function _clickTheFirstButtonInTheListViewNatively(tabView: tabViewModule.TabView) {
|
function _clickTheFirstButtonInTheListViewNatively(tabView: tabViewModule.TabView) {
|
||||||
if (tabView.android) {
|
if (tabView.android) {
|
||||||
var androidListView = <android.widget.ListView>tabView.android.getChildAt(0);
|
var androidListView = <android.widget.ListView>tabView.android.getChildAt(0);
|
||||||
|
@ -13,5 +13,4 @@ declare module "js-libs/polymer-expressions" {
|
|||||||
*/
|
*/
|
||||||
getValue(model, isBackConvert, changedModel);
|
getValue(model, isBackConvert, changedModel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -402,9 +402,9 @@ var Path = require("js-libs/polymer-expressions/path-parser").Path;
|
|||||||
|
|
||||||
Expression.prototype = {
|
Expression.prototype = {
|
||||||
getValue: function (model, isBackConvert, changedModel, observer) {
|
getValue: function (model, isBackConvert, changedModel, observer) {
|
||||||
var value = getFn(this.expression)(model, observer, changedModel);
|
var value = getFn(this.expression)(model.context, observer, changedModel);
|
||||||
for (var i = 0; i < this.filters.length; i++) {
|
for (var i = 0; i < this.filters.length; i++) {
|
||||||
value = this.filters[i].transform(model, observer, model, isBackConvert, [value]);
|
value = this.filters[i].transform(model.context, observer, model.resources, isBackConvert, [value]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
import definition = require("ui/core/bindable");
|
import definition = require("ui/core/bindable");
|
||||||
import dependencyObservable = require("ui/core/dependency-observable");
|
import dependencyObservable = require("ui/core/dependency-observable");
|
||||||
import weakEventListener = require("ui/core/weak-event-listener");
|
import weakEventListener = require("ui/core/weak-event-listener");
|
||||||
|
import appModule = require("application");
|
||||||
import types = require("utils/types");
|
import types = require("utils/types");
|
||||||
import trace = require("trace");
|
import trace = require("trace");
|
||||||
import polymerExpressions = require("js-libs/polymer-expressions");
|
import polymerExpressions = require("js-libs/polymer-expressions");
|
||||||
@ -12,6 +13,9 @@ var bindingContextProperty = new dependencyObservable.Property(
|
|||||||
new dependencyObservable.PropertyMetadata(undefined, dependencyObservable.PropertyMetadataSettings.Inheritable) // TODO: Metadata options?
|
new dependencyObservable.PropertyMetadata(undefined, dependencyObservable.PropertyMetadataSettings.Inheritable) // TODO: Metadata options?
|
||||||
);
|
);
|
||||||
|
|
||||||
|
var contextKey = "context";
|
||||||
|
var resourcesKey = "resources";
|
||||||
|
|
||||||
export class Bindable extends dependencyObservable.DependencyObservable implements definition.Bindable {
|
export class Bindable extends dependencyObservable.DependencyObservable implements definition.Bindable {
|
||||||
|
|
||||||
public static bindingContextProperty = bindingContextProperty;
|
public static bindingContextProperty = bindingContextProperty;
|
||||||
@ -99,11 +103,6 @@ export class Bindable extends dependencyObservable.DependencyObservable implemen
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (binding.source && binding.source.get() !== oldValue) {
|
|
||||||
// Binding has its source set directly, not through binding context, do not bind/unbind in this case
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
trace.write(
|
trace.write(
|
||||||
"Binding target: " + binding.target.get() +
|
"Binding target: " + binding.target.get() +
|
||||||
" targetProperty: " + binding.options.targetProperty +
|
" targetProperty: " + binding.options.targetProperty +
|
||||||
@ -151,7 +150,6 @@ export class Binding {
|
|||||||
obj = new String(obj);
|
obj = new String(obj);
|
||||||
}
|
}
|
||||||
/* tslint:enable */
|
/* tslint:enable */
|
||||||
|
|
||||||
this.source = new WeakRef(obj);
|
this.source = new WeakRef(obj);
|
||||||
this.updateTarget(this.getSourceProperty());
|
this.updateTarget(this.getSourceProperty());
|
||||||
|
|
||||||
@ -159,17 +157,19 @@ export class Binding {
|
|||||||
this.sourceOptions = this.resolveOptions(this.source, this.options.sourceProperty);
|
this.sourceOptions = this.resolveOptions(this.source, this.options.sourceProperty);
|
||||||
}
|
}
|
||||||
|
|
||||||
var sourceOptionsInstance = this.sourceOptions.instance.get();
|
if (this.sourceOptions) {
|
||||||
if (sourceOptionsInstance instanceof observable.Observable) {
|
var sourceOptionsInstance = this.sourceOptions.instance.get();
|
||||||
this.weakEventListenerOptions = {
|
if (sourceOptionsInstance instanceof observable.Observable) {
|
||||||
targetWeakRef: this.target,
|
this.weakEventListenerOptions = {
|
||||||
sourceWeakRef: this.sourceOptions.instance,
|
targetWeakRef: this.target,
|
||||||
eventName: observable.knownEvents.propertyChange,
|
sourceWeakRef: this.sourceOptions.instance,
|
||||||
handler: this.onSourcePropertyChanged,
|
eventName: observable.knownEvents.propertyChange,
|
||||||
handlerContext: this,
|
handler: this.onSourcePropertyChanged,
|
||||||
key: this.options.targetProperty
|
handlerContext: this,
|
||||||
|
key: this.options.targetProperty
|
||||||
|
}
|
||||||
|
this.weakEL.addWeakEventListener(this.weakEventListenerOptions);
|
||||||
}
|
}
|
||||||
this.weakEL.addWeakEventListener(this.weakEventListenerOptions);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,13 +180,22 @@ export class Binding {
|
|||||||
|
|
||||||
this.weakEL.removeWeakEventListener(this.weakEventListenerOptions);
|
this.weakEL.removeWeakEventListener(this.weakEventListenerOptions);
|
||||||
this.weakEventListenerOptions = undefined;
|
this.weakEventListenerOptions = undefined;
|
||||||
this.source.clear();
|
if (this.source) {
|
||||||
this.sourceOptions.instance.clear();
|
this.source.clear();
|
||||||
this.sourceOptions = undefined;
|
}
|
||||||
this.targetOptions = undefined;
|
if (this.sourceOptions) {
|
||||||
|
this.sourceOptions.instance.clear();
|
||||||
|
this.sourceOptions = undefined;
|
||||||
|
}
|
||||||
|
if (this.targetOptions) {
|
||||||
|
this.targetOptions = undefined;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public updateTwoWay(value: any) {
|
public updateTwoWay(value: any) {
|
||||||
|
if (this.updating) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (this.options.twoWay) {
|
if (this.options.twoWay) {
|
||||||
if (this._isExpression(this.options.expression)) {
|
if (this._isExpression(this.options.expression)) {
|
||||||
var changedModel = {};
|
var changedModel = {};
|
||||||
@ -220,7 +229,10 @@ export class Binding {
|
|||||||
var exp = polymerExpressions.PolymerExpressions.getExpression(expression);
|
var exp = polymerExpressions.PolymerExpressions.getExpression(expression);
|
||||||
if (exp) {
|
if (exp) {
|
||||||
var context = this.source && this.source.get && this.source.get() || global;
|
var context = this.source && this.source.get && this.source.get() || global;
|
||||||
return exp.getValue(context, isBackConvert, changedModel);
|
var model = {};
|
||||||
|
model[contextKey] = context;
|
||||||
|
model[resourcesKey] = appModule.resources;
|
||||||
|
return exp.getValue(model, isBackConvert, changedModel);
|
||||||
}
|
}
|
||||||
return new Error(expression + " is not a valid expression.");
|
return new Error(expression + " is not a valid expression.");
|
||||||
}
|
}
|
||||||
@ -261,12 +273,14 @@ export class Binding {
|
|||||||
|
|
||||||
var value;
|
var value;
|
||||||
|
|
||||||
var sourceOptionsInstance = this.sourceOptions.instance.get();
|
if (this.sourceOptions) {
|
||||||
if (sourceOptionsInstance instanceof observable.Observable) {
|
var sourceOptionsInstance = this.sourceOptions.instance.get();
|
||||||
value = sourceOptionsInstance.get(this.sourceOptions.property);
|
if (sourceOptionsInstance instanceof observable.Observable) {
|
||||||
} else if (sourceOptionsInstance && this.sourceOptions.property &&
|
value = sourceOptionsInstance.get(this.sourceOptions.property);
|
||||||
this.sourceOptions.property in sourceOptionsInstance) {
|
} else if (sourceOptionsInstance && this.sourceOptions.property &&
|
||||||
value = sourceOptionsInstance[this.sourceOptions.property];
|
this.sourceOptions.property in sourceOptionsInstance) {
|
||||||
|
value = sourceOptionsInstance[this.sourceOptions.property];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
@ -308,11 +322,12 @@ export class Binding {
|
|||||||
currentObject = currentObject[properties[i]];
|
currentObject = currentObject[properties[i]];
|
||||||
}
|
}
|
||||||
|
|
||||||
options = {
|
if (currentObject !== undefined && currentObject !== null) {
|
||||||
instance: new WeakRef(currentObject),
|
options = {
|
||||||
property: properties[properties.length - 1]
|
instance: new WeakRef(currentObject),
|
||||||
|
property: properties[properties.length - 1]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
options = {
|
options = {
|
||||||
instance: obj,
|
instance: obj,
|
||||||
@ -324,8 +339,15 @@ export class Binding {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private updateOptions(options: { instance: WeakRef<any>; property: any }, value: any) {
|
private updateOptions(options: { instance: WeakRef<any>; property: any }, value: any) {
|
||||||
|
var optionsInstance;
|
||||||
|
if (options && options.instance) {
|
||||||
|
optionsInstance = options.instance.get();
|
||||||
|
}
|
||||||
|
if (!optionsInstance) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.updating = true;
|
this.updating = true;
|
||||||
var optionsInstance = options.instance.get();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (optionsInstance instanceof observable.Observable) {
|
if (optionsInstance instanceof observable.Observable) {
|
||||||
|
@ -155,5 +155,5 @@ function getExports(instance: view.View): any {
|
|||||||
parent = parent.parent;
|
parent = parent.parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (<any>parent).exports;
|
return parent ? (<any>parent).exports : undefined;
|
||||||
}
|
}
|
Reference in New Issue
Block a user