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 keys_pipe which uses Object.keys in order to transform
an object to array of its keys.

Fix angular#2246
  • Loading branch information
harunurhan committed Feb 15, 2018
1 parent 0aa9b46 commit ea9ae72
Show file tree
Hide file tree
Showing 7 changed files with 101 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, KeysPipe, 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';
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 {KeysPipe} from './keys_pipe';
import {CurrencyPipe, DecimalPipe, PercentPipe} from './number_pipe';
import {SlicePipe} from './slice_pipe';

Expand All @@ -28,6 +29,7 @@ export {
I18nPluralPipe,
I18nSelectPipe,
JsonPipe,
KeysPipe,
LowerCasePipe,
PercentPipe,
SlicePipe,
Expand All @@ -52,4 +54,5 @@ export const COMMON_PIPES = [
DatePipe,
I18nPluralPipe,
I18nSelectPipe,
KeysPipe,
];
29 changes: 29 additions & 0 deletions packages/common/src/pipes/keys_pipe.ts
@@ -0,0 +1,29 @@
/**
* @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 its keys using `Object.keys`.
*
* ### Example
* {@example common/pipes/ts/keys_pipe.ts region='KeysPipe'}
*
* @experimental
*/
@Pipe({ name: 'keys', pure: false })
export class KeysPipe implements PipeTransform {
transform(value: object): Array<string> {
return value != null ? Object.keys(value) : [];
}
}
35 changes: 35 additions & 0 deletions packages/common/test/pipes/keys_pipe_spec.ts
@@ -0,0 +1,35 @@
/**
* @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 { KeysPipe } from '@angular/common';

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

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

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

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/keys_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 KeysPipe
@Component({
selector: 'keys-pipe',
template: `<div *ngFor="let key of object | keys">
key is {{key}} and value is {{object[key]}}
</div>`
})
export class KeysPipeComponent {
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 {KeysPipeComponent} from './keys_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, KeysPipeComponent
],
imports: [BrowserModule],
bootstrap: [ExampleAppComponent]
Expand Down
5 changes: 5 additions & 0 deletions tools/public_api_guard/common/common.d.ts
Expand Up @@ -180,6 +180,11 @@ export declare class JsonPipe implements PipeTransform {
transform(value: any): string;
}

/** @experimental */
export declare class KeysPipe implements PipeTransform {
transform(value: object): Array<string>;
}

/** @stable */
export declare class Location {
constructor(platformStrategy: LocationStrategy);
Expand Down

0 comments on commit ea9ae72

Please sign in to comment.