How to add a component programmatically in Angular.Dart? How to add a component programmatically in Angular.Dart? dart dart

How to add a component programmatically in Angular.Dart?


The API has changed in AngularDart 0.9.9:

  • BlockFactory now is ViewFactory
  • scope.$new now seems to be scope.createChild(scope.context)
  • injector.createChild(modules) now requires a list of modules (instead of a single one)

AngularDart 0.10.0 introduces these changes:

  • NgShadowRootAware not is ShadowRootAware
  • ..value() now is ..bind(., toValue: .)

So the code of pavelgj now looks like so:

class AppComponent extends ShadowRootAware {  Compiler compiler;  Injector injector;  Scope scope;  DirectiveMap directives;  AppComponent(this.compiler, this.injector, this.scope, this.directives);  void onShadowRoot(ShadowRoot shadowRoot) {    DivElement inner = shadowRoot.querySelector("#inner");    inner.appendHtml("<inner-comp></inner-comp>");        ViewFactory template = compiler([inner], directives);    Scope childScope = scope.createChild(scope.context);    Injector childInjector =         injector.createChild([new Module()..bind(Scope, toValue: childScope)]);    template(childInjector, [inner]);    }  }


This would be a proper use of the block API.

class AppComponent extends NgShadowRootAware {  Compiler compiler;  Injector injector;  Scope scope;  DirectiveMap directives;  AppComponent(this.compiler, this.injector, this.scope, this.directives);  void onShadowRoot(ShadowRoot shadowRoot) {    DivElement inner = shadowRoot.querySelector("#inner");    inner.appendHtml("<inner-comp></inner-comp>");        BlockFactory template = compiler([inner], directives);    Scope childScope = scope.$new();    Injector childInjector =         injector.createChild(new Module()..value(Scope, childScope));    template(childInjector, [inner]);  }}

Also, if you ever need to recompile the inner template make sure you do childScope.$destroy() on the previous childScope.


The above code samples on longer work because of changes in the Angular Dart library. Specifically ViewFactory.call which no longer takes an injector but takes a Scope and a DirectiveInjector. I've tried adapting what's above and I get very close. The component shows up but none of the bindings are replaced (I see {{cmp.value}} for example.

Here's the code I'm using. I think the issue here is that DirectiveInjector is coming in as null.

void main() {  IBMModule module = new IBMModule();  AngularModule angularModule = new AngularModule();  Injector injector = applicationFactory()  .addModule(module)  .run();  AppComponent appComponent = injector.get(AppComponent);  appComponent.addElement("<brazos-input-string label='test'/>");}@Injectable()class AppComponent {  NodeValidator validator;  Compiler _compiler;  DirectiveInjector _injector;  DirectiveMap _directiveMap;  NodeTreeSanitizer _nodeTreeSanitizer;  Scope _scope;  AppComponent(this._injector, this._compiler, this._directiveMap, this._scope, this._nodeTreeSanitizer) {    validator = new NodeValidatorBuilder.common()                      ..allowCustomElement("BRAZOS-INPUT-STRING")                      ..allowHtml5()                      ..allowTemplating();  }  void addElement(String elementHTML) {    DivElement container = querySelector("#container");    DivElement inner = new DivElement();    inner.setInnerHtml(elementHTML, validator: validator);    ViewFactory viewFactory = _compiler.call([inner], _directiveMap);    Scope childScope = _scope.createChild(new PrototypeMap(_scope.context));    if (_injector == null) {      print("injector is null");    }    View newView = viewFactory.call(childScope, _injector);    container.append(inner);    newView.nodes.forEach((node) => inner.append(node));  }}class IBMModule extends Module {  IBMModule() {    bind(BrazosInputStringComponent);    bind(BrazosTextAreaComponent);    bind(BrazosButtonComponent);    bind(ProcessDataProvider, toImplementation: ActivitiDataProvider);    bind(AppComponent);  }}