0

I have many directives built in an Angular 1.x application. Those directives are used by various internal applications at my company. I'd like for those applications to not have to change their code, but instead abstract many of those syntax changes within my directives as I upgrade to Angular 2.x. For example let's say I have the following directive:

<my-directive
    my-first-attribute="vm.someProperty" 
    my-second-attribute="vm.someFunction()"
></my-directive>

Assume I can't change that syntax from the parent component's perspective Those attributes need to be transformed to something like:

[myFirstAttribute]="vm.someProperty"
(click)="vm.someFunction()"

There used to be a compile function where I could make many of these template changes before linking. Now I've got my constructor function where I can pull in an ElementRef, and DynamicComponentLoader

However, how can I provide vm to my dynamically loaded component?

I've tried:

this._loader.loadIntoLocation(SubCmp, this._el, 'container')
.then((compRef:ComponentRef) => {
  compRef.instance.vm = this.vm;
});

but the component that leverages DynamicComponentLoader itself doesn't know about the vm. I really don't want to change the HTML syntax that invokes the component which in turns dynamically loads its own child components. Here is my current plunkr, which is using Angular 2 beta 15.

bodine
  • 1,763
  • 4
  • 19
  • 28

2 Answers2

0

The reason is that you forgot brackets []:

[model]="model.firstName"

If we forget the brackets, Angular treats the string as a constant and initializes the target property with that string. It does not evaluate the string!

see doc, plunkr

Assuming you can not change templates there are no clean ways to fulfill your requirements. I would not recommend using it, but i wanted to try angular-expressions library, check this plunkr

Idea is to get parent context through injector hierarchy and parse expressions manually.

//i don't fully understand why component index is 0
var context = injector.parent.getAt(0);

//create parser for this.model expression, i.e. 'model.firstName'
var evaluate = angularExpressions.compile(this.model);

//apply value from context
comp.model = evaluate(context);
kemsky
  • 14,727
  • 3
  • 32
  • 51
  • I'm afraid this might be my best bet. However, I didn't actually forget the brackets. I asked for a solution that didn't involve me changing existing template syntax. Ideally, I'd like to abstract that away in the new version of the component I'm updating to use angular 2. Is there any other way of getting the model from the parent component into the child component? – bodine Apr 21 '16 at 21:54
0

For communication with components added by DCL using a shared service is usually the way to go. Some ancestor provides the service and the DCL-added component injects it

@Injectable()
class Model {
  value:string = 'xxx';
}
export class InputCmp {
  constructor(private model:Model){}
  ...
}
@Component({
    selector: 'textbox',
...
    providers: [Model]
})
export class Textbox implements OnInit {
  ...
}

Plunker example

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • I updated my plunkr: http://plnkr.co/edit/fHD19h2hQHYJDy5KNIGD?p=preview Problem is I'm still not getting the 2-way data binding. The docs suggest using the providers array will result in a second instance: https://angular.io/docs/ts/latest/tutorial/toh-pt4.html#!#appendix-shadowing-the-parent-s-service Basically, I want the appcomponent's model and the InputCmp's model to be the same model and update each other accordingly. Can you see what I'm doing wrong? – bodine Apr 25 '16 at 17:40
  • The problem is that you are passing primitive values to the dynamically loaded component. Primitive values are copied and the reference to the original model is lost. If you change it to objects it works as expected http://plnkr.co/edit/FVxdZvxCsKVbvXZ7T8F1?p=preview – Günter Zöchbauer Apr 26 '16 at 13:17
  • DynamicComponentLoader has changed in beta.16. See https://github.com/angular/angular/pull/8234 and http://stackoverflow.com/questions/36325212/angular-2-dynamic-tabs-with-user-click-chosen-components/36325468#36325468 – Günter Zöchbauer Apr 26 '16 at 13:20