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 * as TKUnit from '../../tk-unit';
|
||||
import * as helper from '../../ui-helper';
|
||||
import { Application, Label, Page, StackLayout, WrapLayout, LayoutBase, View, GestureTypes, Repeater, ObservableArray } from '@nativescript/core';
|
||||
import { Application, Label, Page, StackLayout, WrapLayout, LayoutBase, View, KeyedTemplate, GestureTypes, Repeater, ObservableArray } from '@nativescript/core';
|
||||
|
||||
var FEW_ITEMS = [0, 1, 2];
|
||||
var MANY_ITEMS = [];
|
||||
@@ -8,6 +8,18 @@ for (var i = 0; i < 100; i++) {
|
||||
MANY_ITEMS[i] = i;
|
||||
}
|
||||
|
||||
const ITEM_TEMPLATES_STRING = `
|
||||
<template key="red">
|
||||
<Label text='red' style.backgroundColor='red' minHeight='100' maxHeight='100'/>
|
||||
</template>
|
||||
<template key='green'>
|
||||
<Label text='green' style.backgroundColor='green' minHeight='100' maxHeight='100'/>
|
||||
</template>
|
||||
<template key='blue'>
|
||||
<Label text='blue' style.backgroundColor='blue' minHeight='100' maxHeight='100'/>
|
||||
</template>
|
||||
`;
|
||||
|
||||
export function test_recycling() {
|
||||
const setters = new Map<string, StackLayout>();
|
||||
setters.set('itemsLayout', new StackLayout());
|
||||
@@ -309,6 +321,117 @@ export function test_ItemTemplateFactoryFunction() {
|
||||
helper.buildUIAndRunTest(repeater, testAction);
|
||||
}
|
||||
|
||||
// Multiple item templates tests
|
||||
export function test_ItemTemplateSelector_WhenWrongTemplateKeyIsSpecified_TheDefaultTemplateIsUsed() {
|
||||
var repeater = new Repeater();
|
||||
|
||||
function testAction(views: Array<View>) {
|
||||
repeater.itemTemplate = "<Label text='default' minHeight='100' maxHeight='100'/>";
|
||||
repeater.itemTemplates = ITEM_TEMPLATES_STRING;
|
||||
repeater.itemTemplateSelector = "age == 20 ? 'wrong' : 'green'";
|
||||
repeater.items = [{ age: 20 }, { age: 25 }];
|
||||
|
||||
TKUnit.waitUntilReady(() => repeater.isLayoutValid);
|
||||
|
||||
const firstElement = getChildAt(repeater, 0);
|
||||
TKUnit.assertEqual((<Label>firstElement).text, 'default', 'first element text');
|
||||
}
|
||||
|
||||
helper.buildUIAndRunTest(repeater, testAction);
|
||||
}
|
||||
|
||||
export function test_ItemTemplateSelector_IsCorrectlyParsedFromString() {
|
||||
var repeater = new Repeater();
|
||||
|
||||
function testAction(views: Array<View>) {
|
||||
repeater.itemTemplates = ITEM_TEMPLATES_STRING;
|
||||
repeater.itemTemplateSelector = "age < 25 ? 'red' : 'green'";
|
||||
repeater.items = [{ age: 20 }, { age: 25 }];
|
||||
let itemTemplateSelectorFunction = <any>repeater.itemTemplateSelector;
|
||||
|
||||
TKUnit.waitUntilReady(() => repeater.isLayoutValid);
|
||||
|
||||
let templateKey0 = itemTemplateSelectorFunction(repeater.items[0], 0, repeater.items);
|
||||
TKUnit.assertEqual(templateKey0, 'red', 'itemTemplateSelector result for first item');
|
||||
|
||||
let templateKey1 = itemTemplateSelectorFunction(repeater.items[1], 1, repeater.items);
|
||||
TKUnit.assertEqual(templateKey1, 'green', 'itemTemplateSelector result for second item');
|
||||
}
|
||||
|
||||
helper.buildUIAndRunTest(repeater, testAction);
|
||||
}
|
||||
|
||||
export function test_ItemTemplateSelector_IsCorrectlyUsedAsAFunction() {
|
||||
var repeater = new Repeater();
|
||||
|
||||
function testAction(views: Array<View>) {
|
||||
repeater.itemTemplates = ITEM_TEMPLATES_STRING;
|
||||
repeater.itemTemplateSelector = function (item, index: number, items) {
|
||||
return item.age < 25 ? 'red' : 'green';
|
||||
};
|
||||
repeater.items = [{ age: 20 }, { age: 25 }];
|
||||
let itemTemplateSelectorFunction = <any>repeater.itemTemplateSelector;
|
||||
|
||||
TKUnit.waitUntilReady(() => repeater.isLayoutValid);
|
||||
|
||||
let templateKey0 = itemTemplateSelectorFunction(repeater.items[0], 0, repeater.items);
|
||||
TKUnit.assertEqual(templateKey0, 'red', 'itemTemplateSelector result for first item');
|
||||
|
||||
let templateKey1 = itemTemplateSelectorFunction(repeater.items[1], 1, repeater.items);
|
||||
TKUnit.assertEqual(templateKey1, 'green', 'itemTemplateSelector result for second item');
|
||||
}
|
||||
|
||||
helper.buildUIAndRunTest(repeater, testAction);
|
||||
}
|
||||
|
||||
export function test_ItemTemplateSelector_ItemTemplatesAreCorrectlyParsedFromString() {
|
||||
var repeater = new Repeater();
|
||||
|
||||
function testAction(views: Array<View>) {
|
||||
repeater.itemTemplates = ITEM_TEMPLATES_STRING;
|
||||
|
||||
TKUnit.waitUntilReady(() => repeater.isLayoutValid);
|
||||
|
||||
let itemTemplatesArray = <any>repeater.itemTemplates;
|
||||
|
||||
TKUnit.assertEqual(itemTemplatesArray.length, 3, 'itemTemplates array length');
|
||||
|
||||
let template0 = <KeyedTemplate>itemTemplatesArray[0];
|
||||
TKUnit.assertEqual(template0.key, 'red', 'template0.key');
|
||||
TKUnit.assertEqual((<Label>template0.createView()).text, 'red', 'template0 created view text');
|
||||
|
||||
let template1 = <KeyedTemplate>itemTemplatesArray[1];
|
||||
TKUnit.assertEqual(template1.key, 'green', 'template1.key');
|
||||
TKUnit.assertEqual((<Label>template1.createView()).text, 'green', 'template1 created view text');
|
||||
|
||||
let template2 = <KeyedTemplate>itemTemplatesArray[2];
|
||||
TKUnit.assertEqual(template2.key, 'blue', 'template2.key');
|
||||
TKUnit.assertEqual((<Label>template2.createView()).text, 'blue', 'template2 created view text');
|
||||
}
|
||||
|
||||
helper.buildUIAndRunTest(repeater, testAction);
|
||||
}
|
||||
|
||||
export function test_ItemTemplateSelector_CorrectTemplateIsUsed() {
|
||||
var repeater = new Repeater();
|
||||
|
||||
function testAction(views: Array<View>) {
|
||||
repeater.itemTemplates = ITEM_TEMPLATES_STRING;
|
||||
repeater.itemTemplateSelector = "age == 25 ? 'green' : 'red'";
|
||||
repeater.items = [{ age: 20 }, { age: 25 }];
|
||||
|
||||
TKUnit.waitUntilReady(() => repeater.isLayoutValid);
|
||||
|
||||
const firstElement = getChildAt(repeater, 0);
|
||||
const secondElement = getChildAt(repeater, 1);
|
||||
|
||||
TKUnit.assertEqual((<Label>firstElement).text, 'red', 'first element text');
|
||||
TKUnit.assertEqual((<Label>secondElement).text, 'green', 'second element text');
|
||||
}
|
||||
|
||||
helper.buildUIAndRunTest(repeater, testAction);
|
||||
}
|
||||
|
||||
export function test_BindingRepeaterToASimpleArrayWithExpression() {
|
||||
var repeater = new Repeater();
|
||||
|
||||
|
||||
@@ -16,6 +16,16 @@ Other modules which will be used in the code samples in this article:
|
||||
{%raw%}<Repeater items="{{ myItems }}" />{%endraw%}
|
||||
</Page>
|
||||
```
|
||||
### Define the Repeater itemsLayout property. Default is StackLayout with orientation="vertical".
|
||||
``` XML
|
||||
<Page>
|
||||
{%raw%}<Repeater items="{{ myItems }}">
|
||||
<Repeater.itemsLayout>
|
||||
<StackLayout orientation="horizontal" />
|
||||
</Repeater.itemsLayout>
|
||||
</Repeater>{%endraw%}
|
||||
</Page>
|
||||
```
|
||||
### Define the Repeater itemTemplate property.
|
||||
``` XML
|
||||
<Page>
|
||||
@@ -26,13 +36,52 @@ Other modules which will be used in the code samples in this article:
|
||||
</Repeater>{%endraw%}
|
||||
</Page>
|
||||
```
|
||||
### Define the Repeater itemsLayout property. Default is StackLayout with orientation="vertical".
|
||||
### Define multiple item templates and an item template selector in XML.
|
||||
The itemTemplateSelector can be an expression specified directly in XML. The context of the expression is the data item for each row.
|
||||
``` XML
|
||||
<Page>
|
||||
{%raw%}<Repeater items="{{ myItems }}">
|
||||
<Repeater.itemsLayout>
|
||||
<StackLayout orientation="horizontal" />
|
||||
</Repeater.itemsLayout>
|
||||
{%raw%}<Repeater items="{{ myItems }}" itemTemplateSelector="age > 18 ? 'green' : 'red'">
|
||||
<Repeater.itemTemplates>
|
||||
<template key="green">
|
||||
<Label text="{{ age }}" style.backgroundColor="green" />
|
||||
</template>
|
||||
<template key="red">
|
||||
<Label text="{{ age }}" style.backgroundColor="red" />
|
||||
</template>
|
||||
</Repeater.itemTemplates>
|
||||
</Repeater>{%endraw%}
|
||||
</Page>
|
||||
```
|
||||
### Specifying the item template selector as a function in the code-behind file
|
||||
In case your item template selector involves complicated logic which cannot be expressed with an expression, you can create an item template selector function in the code behind of the page in which the RepeaterRepeater resides. The function receives the respective data item, the row index and the entire Repeater items collection as parameters. It has to return the the key of the template to be used based on the supplied information.
|
||||
``` XML
|
||||
<Page>
|
||||
{%raw%}<Repeater items="{{ myItems }}" itemTemplateSelector="selectItemTemplate">
|
||||
<Repeater.itemTemplates>
|
||||
<template key="green">
|
||||
<Label text="{{ age }}" style.backgroundColor="green" />
|
||||
</template>
|
||||
<template key="red">
|
||||
<Label text="{{ age }}" style.backgroundColor="red" />
|
||||
</template>
|
||||
</Repeater.itemTemplates>
|
||||
</Repeater>{%endraw%}
|
||||
</Page>
|
||||
```
|
||||
{%snippet article-item-template-selector-function%}
|
||||
### Alternating row colors
|
||||
You can use the special value '$index' in the item template selector expression which represents the row index.
|
||||
``` XML
|
||||
<Page>
|
||||
{%raw%}<Repeater items="{{ myItems }}" itemTemplateSelector="$index % 2 === 0 ? 'even' : 'odd'">
|
||||
<Repeater.itemTemplates>
|
||||
<template key="even">
|
||||
<Label text="{{ age }}" style.backgroundColor="white" />
|
||||
</template>
|
||||
<template key="odd">
|
||||
<Label text="{{ age }}" style.backgroundColor="gray" />
|
||||
</template>
|
||||
</Repeater.itemTemplates>
|
||||
</Repeater>{%endraw%}
|
||||
</Page>
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user