1

Quite often I need to use stream of input values in component. Usually I do it in this way:

export class UserComponent {
    userId$ = new BehaviorSubject<number>(null);
    @Input() set userId(value: number) {
       this.userId$.next(value);
    }
}

I wonder is there a way to create Input$ decorator:

export class UserComponent {
    @Input$() userId$ = new BehaviorSubject<number>(null);
}

1 Answer 1

3

Yes, it is possible, you could create additional decorator which will replace class field with getter/setter pair, getter will return Subject and setter will do next on this subject.

Please note that it will likely break AOT compilation.

@Input()
@Reactive(false)
public subject:Subject<boolean>; //you don't even need to initialize

export function Reactive(initialValue:any):Function
{
    return function(target:Object, property:string)
    {
        const name:string = `__subject_${property}`;

        Object.defineProperty(target, name, <PropertyDescriptor>{
            enumerable  : false,
            configurable: false,
            writable    : true
        });

        Object.defineProperty(target, property, <PropertyDescriptor>{
            enumerable  : true,
            configurable: false,
            get         : function():any
            {
                if(this[name] === undefined)
                {
                    this[name] = new BehaviorSubject<any>(initialValue);
                }
                return this[name];
            },
            set         : function(val:any):void
            {
                if(this[name] === undefined)
                {
                    this[name] = new BehaviorSubject<any>(initialValue);
                }
                this[name].next(val);
            }
        });
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

Looks great, thank you. Can you elaborate, why you think it will break AoT?
Type checking is more strict in AOT mode and attempt to assign i.e. string value to Subject<string> field may fail. In order to preserve compatibility it makes sense to create decorator for automatic binding input to existing subject, i.e. @Input() @Reactive<UserComponent>(x => x.subject) bool:boolean;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.