11
votes

I'm using AngularDart and routing. My views are one-liners that contain a single component. I feel the views are not carrying their weight. Can I route directly to a component?


Example:

router.root
  ..addRoute(
      name: 'welcome',
      path: '/welcome',
      defaultRoute: true,
      enter: view('views/welcome.html'))
  ..addRoute(
      name: 'camera',
      path: '/camera',
      enter: view('views/camera.html'));

And here's views/welcome.html

<welcome></welcome>

And here's views/camera.html

<camera></camera>

As you can see, those views are pretty weak. I'm much rather say: "when you enter a view, insert this component"

Is that possible?

2

2 Answers

6
votes

This seems to be directly supported now

see https://github.com/angular/angular.dart/issues/425

You can route to an inline template (viewHtml):

views.configure({
  'foo': ngRoute(
      path: '/foo',
      viewHtml: '<foo-component></foo-component>')
});
4
votes

I wanted to ask the same question, but you were the first! I found a solution, probably not the best one, but at least it works.

I created one html for all routes:

dyn_view.html:

<div><dynamic-view></dynamic-view></div>

and of course a component dynamic-view, which takes actual component tag name from the route provider and dynamically adds to the DOM using the technique described here: How to add a component programatically in Angular.Dart?

dynamic_view.html

<div></div>

dynamic_view.dart

@NgComponent(
    selector: 'dynamic-view',
    templateUrl: 'view/dynamic_view.html'
)
class DynamicView implements NgShadowRootAware {
  Compiler compiler;
  Injector injector;
  String elementName;

  DynamicView(this.compiler, this.injector, RouteProvider provider) {  
    elementName = provider.parameters["elementName"];
  }

  void onShadowRoot(ShadowRoot shadowRoot) {
    DivElement inner = shadowRoot.querySelector("div");
    inner.appendHtml("<$elementName></$elementName>");    
    BlockFactory template = compiler(inner.nodes);
    var block = template(injector);
    inner.replaceWith(block.elements[0]); 
  }
}

Now the router. The element name must be passed somehow to the RouteProvider. I was inspired by this post: Verifying route preconditions prior to loading controller

class DynamicViewFactory {
  ViewFactory viewFactory;
  DynamicViewFactory(this.viewFactory);

  call(String elementName) {
     return (RouteEvent event) {
       event.parameters["elementName"] = elementName;
       viewFactory("view/dyn_view.html")(event);
     };
  }
}



class MyRouteInitializer implements RouteInitializer {

  init(Router router, ViewFactory view) {
    DynamicViewFactory dynView = new DynamicViewFactory(view);
    router.root
      ..addRoute(
          name: 'route1',
          path: '/a/:b',
          enter: dynView('componentA'))
      ..addRoute(
          name: 'route2',
          path: '/b/:c',
          enter: dynView('componentB'));
  }
}

The above code is slightly modified from what actually I use, so it can have some small bugs, but the general idea is the same.

Hope that helps!