diff --git a/src/builtin/filters/array.ts b/src/builtin/filters/array.ts index 2e539d9d90..2243112122 100644 --- a/src/builtin/filters/array.ts +++ b/src/builtin/filters/array.ts @@ -2,16 +2,26 @@ import { isArray, last as arrayLast } from '../../util/underscore' import { toArray } from '../../util/collection' import { isTruthy } from '../../render/boolean' import { FilterImpl } from '../../template/filter/filter-impl' +import { Scope } from '../../context/scope' export const join = (v: any[], arg: string) => v.join(arg === undefined ? ' ' : arg) export const last = (v: any) => isArray(v) ? arrayLast(v) : '' export const first = (v: any) => isArray(v) ? v[0] : '' export const reverse = (v: any[]) => [...v].reverse() -export const sort = (v: T[], arg: (lhs: T, rhs: T) => number) => v.sort(arg) + +export function sort (this: FilterImpl, arr: T[], property?: string) { + const getValue = (obj: Scope) => property ? this.context.getFromScope(obj, property.split('.')) : obj + return toArray(arr).sort((lhs, rhs) => { + lhs = getValue(lhs) + rhs = getValue(rhs) + return lhs < rhs ? -1 : (lhs > rhs ? 1 : 0) + }) +} + export const size = (v: string | any[]) => (v && v.length) || 0 -export function map (arr: {[key: string]: T1}[], arg: string): T1[] { - return toArray(arr).map(v => v[arg]) +export function map (this: FilterImpl, arr: Scope[], property: string) { + return toArray(arr).map(obj => this.context.getFromScope(obj, property.split('.'))) } export function concat (v: T1[], arg: T2[] | T2): (T1 | T2)[] { diff --git a/test/integration/builtin/filters/array.ts b/test/integration/builtin/filters/array.ts index e519f7f76d..583586e93b 100644 --- a/test/integration/builtin/filters/array.ts +++ b/test/integration/builtin/filters/array.ts @@ -42,6 +42,13 @@ describe('filters/array', function () { const post = { category: 'foo' } return test('{{post | map: "category"}}', { post }, 'foo') }) + it('should support nested property', function () { + const tpl = '{{ arr | map: "name.first" | join }}' + const a = { name: { first: 'Alice' } } + const b = { name: { first: 'Bob' } } + const c = { name: { first: 'Carol' } } + return test(tpl, { arr: [a, b, c] }, 'Alice Bob Carol') + }) }) describe('reverse', function () { it('should support reverse', () => test( @@ -106,11 +113,25 @@ describe('filters/array', function () { it('should slice substr by -2,2', () => test('{{ "abc" | slice: -2, 2 }}', 'bc')) it('should support array', () => test('{{ "1,2,3,4" | split: "," | slice: 1,2 | join }}', '2 3')) }) - it('should support sort', function () { - return test('{% assign my_array = "zebra, octopus, giraffe, Sally Snake"' + - ' | split: ", " %}' + - '{{ my_array | sort | join: ", " }}', - 'Sally Snake, giraffe, octopus, zebra') + describe('sort', function () { + it('should support sort', function () { + return test('{% assign my_array = "zebra, octopus, giraffe, Sally Snake"' + + ' | split: ", " %}' + + '{{ my_array | sort | join: ", " }}', + 'Sally Snake, giraffe, octopus, zebra') + }) + it('should support sort by key', function () { + const tpl = '{{ arr | sort: "name" | map: "name" | join }}' + const arr = [{ name: 'Bob' }, { name: 'Carol' }, { name: 'Alice' }] + return test(tpl, { arr }, 'Alice Bob Carol') + }) + it('should support sort by nested property', function () { + const tpl = '{{ arr | sort: "name.first" | map: "name.first" | join }}' + const a = { name: { first: 'Alice' } } + const b = { name: { first: 'Bob' } } + const c = { name: { first: 'Carol' } } + return test(tpl, { arr: [b, c, a, c] }, 'Alice Bob Carol Carol') + }) }) describe('uniq', function () { it('should uniq string list', function () {