Skip to content

Commit

Permalink
feat(common): new pipe to support object for ngFor
Browse files Browse the repository at this point in the history
Add entries_pipe which uses Object.keys in order to transform
an object to array of its [key, value] pairs

Fix angular#2246
  • Loading branch information
harunurhan committed Feb 16, 2018
1 parent 0aa9b46 commit c88d63e
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 2 deletions.
2 changes: 1 addition & 1 deletion packages/common/src/common.ts
Expand Up @@ -19,7 +19,7 @@ export {parseCookieValue as ɵparseCookieValue} from './cookie';
export {CommonModule, DeprecatedI18NPipesModule} from './common_module';
export {NgClass, NgForOf, NgForOfContext, NgIf, NgIfContext, NgPlural, NgPluralCase, NgStyle, NgSwitch, NgSwitchCase, NgSwitchDefault, NgTemplateOutlet, NgComponentOutlet} from './directives/index';
export {DOCUMENT} from './dom_tokens';
export {AsyncPipe, DatePipe, I18nPluralPipe, I18nSelectPipe, JsonPipe, LowerCasePipe, CurrencyPipe, DecimalPipe, PercentPipe, SlicePipe, UpperCasePipe, TitleCasePipe} from './pipes/index';
export {AsyncPipe, DatePipe, I18nPluralPipe, I18nSelectPipe, JsonPipe, EntriesPipe, LowerCasePipe, CurrencyPipe, DecimalPipe, PercentPipe, SlicePipe, UpperCasePipe, TitleCasePipe} from './pipes/index';
export {DeprecatedDatePipe, DeprecatedCurrencyPipe, DeprecatedDecimalPipe, DeprecatedPercentPipe} from './pipes/deprecated/index';
export {PLATFORM_BROWSER_ID as ɵPLATFORM_BROWSER_ID, PLATFORM_SERVER_ID as ɵPLATFORM_SERVER_ID, PLATFORM_WORKER_APP_ID as ɵPLATFORM_WORKER_APP_ID, PLATFORM_WORKER_UI_ID as ɵPLATFORM_WORKER_UI_ID, isPlatformBrowser, isPlatformServer, isPlatformWorkerApp, isPlatformWorkerUi} from './platform_id';
export {VERSION} from './version';
34 changes: 34 additions & 0 deletions packages/common/src/pipes/entries_pipe.ts
@@ -0,0 +1,34 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

import {Pipe, PipeTransform} from '@angular/core';

/**
* @ngModule CommonModule
* @whatItDoes Transforms an object to array of its keys.
* @howToUse `object_expression | keys`
* @description
*
* Transforms an object to array of `[key, value]` pairs using `Object.keys`.
*
* ### Example
* {@example common/pipes/ts/entries_pipe.ts region='Entries'}
*
* @experimental
*/
@Pipe({name: 'entries', pure: false})
export class EntriesPipe implements PipeTransform {
transform(value: {[key: string]: any}): [string, any][] {
if (value == null) {
return [];
}

return Object.keys(value)
.map(key => <[string, any]> [key, value[key]]);
}
}
3 changes: 3 additions & 0 deletions packages/common/src/pipes/index.ts
Expand Up @@ -17,6 +17,7 @@ import {DatePipe} from './date_pipe';
import {I18nPluralPipe} from './i18n_plural_pipe';
import {I18nSelectPipe} from './i18n_select_pipe';
import {JsonPipe} from './json_pipe';
import {EntriesPipe} from './entries_pipe';
import {CurrencyPipe, DecimalPipe, PercentPipe} from './number_pipe';
import {SlicePipe} from './slice_pipe';

Expand All @@ -28,6 +29,7 @@ export {
I18nPluralPipe,
I18nSelectPipe,
JsonPipe,
EntriesPipe,
LowerCasePipe,
PercentPipe,
SlicePipe,
Expand All @@ -52,4 +54,5 @@ export const COMMON_PIPES = [
DatePipe,
I18nPluralPipe,
I18nSelectPipe,
EntriesPipe,
];
33 changes: 33 additions & 0 deletions packages/common/test/pipes/entries_pipe_spec.ts
@@ -0,0 +1,33 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

import {EntriesPipe} from '@angular/common';

export function main() {
describe('EntriesPipe', () => {
let pipe: EntriesPipe;

beforeEach(() => { pipe = new EntriesPipe(); });

describe('transform', () => {
it('should return key value pairs', () => {
const object = {key1: 'value1', key2: 'value2'};
const entries = [['key1', 'value1'], ['key2', 'value2']];
const val = pipe.transform(object);
expect(val).toEqual(entries);
});

it('should return empty array if value is undefined',
() => { expect(pipe.transform(undefined as any)).toEqual([]); });

it('should return empty array if value is null',
() => { expect(pipe.transform(null as any)).toEqual([]); });

});
});
}
23 changes: 23 additions & 0 deletions packages/examples/common/pipes/ts/entries_pipe.ts
@@ -0,0 +1,23 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

import {Component, NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';

// #docregion EntriesPipe
@Component({
selector: 'entries-pipe',
template: `<div *ngFor="let entry of object | entries">
key is {{entry[0]}} and value is {{entry[1]]}}
</div>`
})
export class EntriesPipeComponent {
object: Object = {key1: 'value1', key2: 'value2'};
}
// #enddocregion
6 changes: 5 additions & 1 deletion packages/examples/common/pipes/ts/module.ts
Expand Up @@ -14,6 +14,7 @@ import {CurrencyPipeComponent, DeprecatedCurrencyPipeComponent} from './currency
import {DatePipeComponent, DeprecatedDatePipeComponent} from './date_pipe';
import {I18nPluralPipeComponent, I18nSelectPipeComponent} from './i18n_pipe';
import {JsonPipeComponent} from './json_pipe';
import {EntriesPipeComponent} from './entries_pipe';
import {LowerUpperPipeComponent} from './lowerupper_pipe';
import {DeprecatedNumberPipeComponent, NumberPipeComponent} from './number_pipe';
import {DeprecatedPercentPipeComponent, PercentPipeComponent} from './percent_pipe';
Expand Down Expand Up @@ -49,6 +50,9 @@ import {SlicePipeListComponent, SlicePipeStringComponent} from './slice_pipe';
<h2><code>i18n</code></h2>
<i18n-plural-pipe></i18n-plural-pipe>
<i18n-select-pipe></i18n-select-pipe>
<h2><code>keys</code></h2>
<keys-pipe></keys-pipe>
`
})
export class ExampleAppComponent {
Expand All @@ -60,7 +64,7 @@ export class ExampleAppComponent {
DatePipeComponent, DeprecatedDatePipeComponent, LowerUpperPipeComponent, NumberPipeComponent,
PercentPipeComponent, DeprecatedPercentPipeComponent, CurrencyPipeComponent,
DeprecatedCurrencyPipeComponent, SlicePipeStringComponent, SlicePipeListComponent,
I18nPluralPipeComponent, I18nSelectPipeComponent
I18nPluralPipeComponent, I18nSelectPipeComponent, EntriesPipeComponent
],
imports: [BrowserModule],
bootstrap: [ExampleAppComponent]
Expand Down
7 changes: 7 additions & 0 deletions tools/public_api_guard/common/common.d.ts
Expand Up @@ -64,6 +64,13 @@ export declare class DeprecatedPercentPipe implements PipeTransform {
/** @stable */
export declare const DOCUMENT: InjectionToken<Document>;

/** @experimental */
export declare class EntriesPipe implements PipeTransform {
transform(value: {
[key: string]: any;
}): [string, any][];
}

/** @experimental */
export declare enum FormatWidth {
Short = 0,
Expand Down

0 comments on commit c88d63e

Please sign in to comment.