Skip to content

Commit

Permalink
fix(TranslatePipe): call markForChanges when the pipe updates a value
Browse files Browse the repository at this point in the history
this should help with ChangeDetectionStrategy.OnPush

Fixes #33
  • Loading branch information
ocombe committed Mar 15, 2016
1 parent 3b2d22a commit 591ee4d
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 12 deletions.
8 changes: 5 additions & 3 deletions bundles/ng2-translate.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ System.registerDynamic("src/translate.pipe", ["angular2/core", "./translate.serv
var translate_service_1 = $__require('./translate.service');
var lang_1 = $__require('angular2/src/facade/lang');
var TranslatePipe = (function() {
function TranslatePipe(translate) {
this.value = '';
function TranslatePipe(translate, _ref) {
this.translate = translate;
this._ref = _ref;
this.value = '';
}
TranslatePipe.prototype.equals = function(o1, o2) {
if (o1 === o2)
Expand Down Expand Up @@ -76,6 +77,7 @@ System.registerDynamic("src/translate.pipe", ["angular2/core", "./translate.serv
var _this = this;
this.translate.get(key, interpolateParams).subscribe(function(res) {
_this.value = res ? res : key;
_this._ref.markForCheck();
});
};
TranslatePipe.prototype.transform = function(query, args) {
Expand Down Expand Up @@ -119,7 +121,7 @@ System.registerDynamic("src/translate.pipe", ["angular2/core", "./translate.serv
TranslatePipe = __decorate([core_1.Injectable(), core_1.Pipe({
name: 'translate',
pure: false
}), __metadata('design:paramtypes', [translate_service_1.TranslateService])], TranslatePipe);
}), __metadata('design:paramtypes', [translate_service_1.TranslateService, core_1.ChangeDetectorRef])], TranslatePipe);
return TranslatePipe;
}());
exports.TranslatePipe = TranslatePipe;
Expand Down
7 changes: 3 additions & 4 deletions src/translate.pipe.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {PipeTransform, Pipe, Injectable, EventEmitter, OnDestroy} from 'angular2/core';
import {PipeTransform, Pipe, Injectable, EventEmitter, OnDestroy, ChangeDetectorRef} from 'angular2/core';
import {TranslateService, LangChangeEvent} from './translate.service';
import {isPresent, isArray} from "angular2/src/facade/lang";

Expand All @@ -8,14 +8,12 @@ import {isPresent, isArray} from "angular2/src/facade/lang";
pure: false // required to update the value when the promise is resolved
})
export class TranslatePipe implements PipeTransform, OnDestroy {
translate: TranslateService;
value: string = '';
lastKey: string;
lastParams: any[];
onLangChange: EventEmitter<LangChangeEvent>;

constructor(translate: TranslateService) {
this.translate = translate;
constructor(private translate: TranslateService, private _ref: ChangeDetectorRef) {
}

/**
Expand Down Expand Up @@ -73,6 +71,7 @@ export class TranslatePipe implements PipeTransform, OnDestroy {
updateValue(key: string, interpolateParams?: Object): void {
this.translate.get(key, interpolateParams).subscribe((res: string) => {
this.value = res ? res : key;
this._ref.markForCheck();
});
}

Expand Down
35 changes: 30 additions & 5 deletions tests/translate.pipe.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,20 @@ import {TranslatePipe} from '../src/translate.pipe';
import {MockConnection, MockBackend} from "angular2/src/http/backends/mock_backend";
import {TRANSLATE_PROVIDERS, TranslateService} from "./../ng2-translate";
import {XHRBackend, HTTP_PROVIDERS} from "angular2/http";
import {provide, Injector} from "angular2/core";
import {provide, Injector, ChangeDetectorRef} from "angular2/core";

class FakeChangeDetectorRef extends ChangeDetectorRef {
markForCheck(): void {}

detach(): void {}

detectChanges(): void {}

checkNoChanges(): void {}

reattach(): void {}

}

export function main() {
describe('TranslatePipe', () => {
Expand All @@ -11,21 +24,22 @@ export function main() {
let translate: TranslateService;
let connection: MockConnection; // this will be set when a new connection is emitted from the backend.
let translatePipe: TranslatePipe;
let ref: any;

beforeEach(() => {
injector = Injector.resolveAndCreate([
HTTP_PROVIDERS,
// Provide a mocked (fake) backend for Http
provide(XHRBackend, {useClass: MockBackend}),
TRANSLATE_PROVIDERS,
TranslatePipe
TRANSLATE_PROVIDERS
]);
backend = injector.get(XHRBackend);
translate = injector.get(TranslateService);
// sets the connection when someone tries to access the backend with an xhr request
backend.connections.subscribe((c: MockConnection) => connection = c);

translatePipe = injector.get(TranslatePipe);
ref = new FakeChangeDetectorRef();
translatePipe = new TranslatePipe(translate, ref);
});

it('is defined', () => {
Expand All @@ -41,6 +55,15 @@ export function main() {
expect(translatePipe.transform('TEST', [])).toEqual("This is a test");
});

it('should call markForChanges when it translates a string', () => {
translate.setTranslation('en', {"TEST": "This is a test"});
translate.use('en');
spyOn(ref, 'markForCheck').and.callThrough();

translatePipe.transform('TEST', []);
expect(ref.markForCheck).toHaveBeenCalled();
});

it('should translate a string with object parameters', () => {
translate.setTranslation('en', {"TEST": "This is a test {{param}}"});
translate.use('en');
Expand All @@ -56,18 +79,20 @@ export function main() {
expect(translatePipe.transform('TEST', ['{"param": "with param"}'])).toEqual("This is a test with param");
});

it('should update the value if the parameters change', () => {
it('should update the value when the parameters change', () => {
translate.setTranslation('en', {"TEST": "This is a test {{param}}"});
translate.use('en');

spyOn(translatePipe, 'updateValue').and.callThrough();
spyOn(ref, 'markForCheck').and.callThrough();

expect(translatePipe.transform('TEST', [{param: "with param"}])).toEqual("This is a test with param");
// same value, shouldn't call 'updateValue' again
expect(translatePipe.transform('TEST', [{param: "with param"}])).toEqual("This is a test with param");
// different param, should call 'updateValue'
expect(translatePipe.transform('TEST', [{param: "with param2"}])).toEqual("This is a test with param2");
expect(translatePipe.updateValue).toHaveBeenCalledTimes(2);
expect(ref.markForCheck).toHaveBeenCalledTimes(2);
});

it("should throw if you don't give an object parameter", () => {
Expand Down

0 comments on commit 591ee4d

Please sign in to comment.