mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-11-05 13:26:48 +08:00
feat(core): Repeater multiple item templates implementation (#8981)
This commit is contained in:
committed by
GitHub
parent
0bbdeaf0b5
commit
b113f1916d
@@ -1,6 +1,6 @@
|
||||
import { Label } from '../label';
|
||||
import { LayoutBase } from '../layouts/layout-base';
|
||||
import { View, CSSType, CustomLayoutView, Template } from '../core/view';
|
||||
import { View, CSSType, CustomLayoutView, Template, KeyedTemplate } from '../core/view';
|
||||
import { Property } from '../core/properties';
|
||||
import { layout } from '../../utils';
|
||||
import { StackLayout } from '../layouts/stack-layout';
|
||||
@@ -19,7 +19,12 @@ export interface ItemsSource {
|
||||
*/
|
||||
@CSSType('Repeater')
|
||||
export class Repeater extends CustomLayoutView {
|
||||
// TODO: get rid of such hacks.
|
||||
public static knownFunctions = ['itemTemplateSelector']; // See component-builder.ts isKnownFunction
|
||||
|
||||
private _isDirty = false;
|
||||
private _itemTemplateSelector: (item: any, index: number, items: any) => string;
|
||||
private _itemTemplateSelectorBindable;
|
||||
public ios;
|
||||
public android;
|
||||
|
||||
@@ -29,6 +34,15 @@ export class Repeater extends CustomLayoutView {
|
||||
this.itemsLayout = new StackLayout();
|
||||
}
|
||||
|
||||
@profile
|
||||
public onLoaded() {
|
||||
if (this._isDirty) {
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
super.onLoaded();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets or set the items collection of the Repeater.
|
||||
* The items property can be set to an array or an object defining length and getItem(index) method.
|
||||
@@ -38,18 +52,44 @@ export class Repeater extends CustomLayoutView {
|
||||
* Gets or set the item template of the Repeater.
|
||||
*/
|
||||
public itemTemplate: string | Template;
|
||||
/**
|
||||
* Gets or set the item templates of the Repeater.
|
||||
*/
|
||||
public itemTemplates: string | Array<KeyedTemplate>;
|
||||
/**
|
||||
* Gets or set the items layout of the Repeater. Default value is StackLayout with orientation="vertical".
|
||||
*/
|
||||
public itemsLayout: LayoutBase;
|
||||
|
||||
@profile
|
||||
public onLoaded() {
|
||||
if (this._isDirty) {
|
||||
this.refresh();
|
||||
}
|
||||
get itemTemplateSelector(): string | ((item: any, index: number, items: any) => string) {
|
||||
return this._itemTemplateSelector;
|
||||
}
|
||||
set itemTemplateSelector(value: string | ((item: any, index: number, items: any) => string)) {
|
||||
if (typeof value === 'string') {
|
||||
if (!this._itemTemplateSelectorBindable) {
|
||||
this._itemTemplateSelectorBindable = new Label();
|
||||
}
|
||||
|
||||
super.onLoaded();
|
||||
this._itemTemplateSelectorBindable.bind({
|
||||
sourceProperty: null,
|
||||
targetProperty: 'templateKey',
|
||||
expression: value,
|
||||
});
|
||||
|
||||
this._itemTemplateSelector = (item: any, index: number, items: any) => {
|
||||
item['$index'] = index;
|
||||
|
||||
if (this._itemTemplateSelectorBindable.bindingContext === item) {
|
||||
this._itemTemplateSelectorBindable.bindingContext = null;
|
||||
}
|
||||
|
||||
this._itemTemplateSelectorBindable.bindingContext = item;
|
||||
|
||||
return this._itemTemplateSelectorBindable.get('templateKey');
|
||||
};
|
||||
} else if (typeof value === 'function') {
|
||||
this._itemTemplateSelector = value;
|
||||
}
|
||||
}
|
||||
|
||||
public _requestRefresh() {
|
||||
@@ -73,8 +113,25 @@ export class Repeater extends CustomLayoutView {
|
||||
|
||||
const length = this.items.length;
|
||||
for (let i = 0; i < length; i++) {
|
||||
const viewToAdd = this.itemTemplate ? Builder.parse(this.itemTemplate, this) : this._getDefaultItemContent(i);
|
||||
const dataItem = this._getDataItem(i);
|
||||
let viewToAdd = null;
|
||||
|
||||
if (this._itemTemplateSelector && this.itemTemplates) {
|
||||
const key = this._itemTemplateSelector(dataItem, i, this.items);
|
||||
const length2 = this.itemTemplates.length;
|
||||
for (let j = 0; j < length2; j++) {
|
||||
const template = <KeyedTemplate>this.itemTemplates[j];
|
||||
if (template.key === key) {
|
||||
viewToAdd = template.createView();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!viewToAdd) {
|
||||
viewToAdd = this.itemTemplate ? Builder.parse(this.itemTemplate, this) : this._getDefaultItemContent(i);
|
||||
}
|
||||
|
||||
viewToAdd.bindingContext = dataItem;
|
||||
this.itemsLayout.addChild(viewToAdd);
|
||||
}
|
||||
@@ -147,7 +204,7 @@ export class Repeater extends CustomLayoutView {
|
||||
Repeater.prototype.recycleNativeView = 'auto';
|
||||
|
||||
/**
|
||||
* Represents the item template property of each ListView instance.
|
||||
* Represents the item template property of each Repeater instance.
|
||||
*/
|
||||
export const itemTemplateProperty = new Property<Repeater, string | Template>({
|
||||
name: 'itemTemplate',
|
||||
@@ -159,7 +216,26 @@ export const itemTemplateProperty = new Property<Repeater, string | Template>({
|
||||
itemTemplateProperty.register(Repeater);
|
||||
|
||||
/**
|
||||
* Represents the property backing the items property of each ListView instance.
|
||||
* Represents the items template property of each Repeater instance.
|
||||
*/
|
||||
export const itemTemplatesProperty = new Property<Repeater, string | Array<KeyedTemplate>>({
|
||||
name: 'itemTemplates',
|
||||
affectsLayout: true,
|
||||
valueConverter: (value) => {
|
||||
if (typeof value === 'string') {
|
||||
return Builder.parseMultipleTemplates(value, null);
|
||||
}
|
||||
|
||||
return value;
|
||||
},
|
||||
valueChanged: (target) => {
|
||||
target._requestRefresh();
|
||||
},
|
||||
});
|
||||
itemTemplatesProperty.register(Repeater);
|
||||
|
||||
/**
|
||||
* Represents the property backing the items property of each Repeater instance.
|
||||
*/
|
||||
export const itemsProperty = new Property<Repeater, any[] | ItemsSource>({
|
||||
name: 'items',
|
||||
|
||||
Reference in New Issue
Block a user