4

I want the component to set the templateUrl with a variable, but it doesn't work.

@Component({
    selector: 'article',
    templateUrl: '{{article.html}}',
    styleUrls: ['styles/stylesheets/article.component.css']
})

export class ArticleComponent implements OnInit {
    constructor(private route: ActivatedRoute, private articleService: ArticleService) { }
    articleArray = this.articleService.getArticles();
    article: Article;

    ngOnInit(): void {
        this.route.params.forEach((params: Params) => {
            let headline = params['headline'];
            this.article = this.articleService.getArticle(headline)
        });
    }

}

Every where I look, I can only see solutions for Angular 1.X, It's really frustrating. I looked into the browser console and figured out that {{article.html}} isn't even resolving. It's reading as it is. It works totally fine when I set the path myself, so I know that the problem isn't anywhere but here.

1
  • I wonder if it is possible ! Commented Sep 9, 2016 at 11:18

1 Answer 1

15

I think you should use dynamic component loading to do that.

Let's say we have a json file:

{
    "title": "My first article",
    "html": "app/articles/first.html"
}

We might create HtmlOutlet directive that will create component dynamicallу with desired templateUrl:

@Directive({
  selector: 'html-outlet' 
})
export class HtmlOutlet {
  @Input() html: string;

  constructor(private vcRef: ViewContainerRef, private compiler: Compiler) {}

  ngOnChanges() {
    const html = this.html;
    if (!html) return;

    @Component({
      selector: 'dynamic-comp',
      templateUrl: html
    })
    class DynamicHtmlComponent  { };

    @NgModule({
      imports: [CommonModule],
      declarations: [DynamicHtmlComponent]
    })
    class DynamicHtmlModule {}

    this.compiler.compileModuleAndAllComponentsAsync(DynamicHtmlModule)
      .then(factory => {
        const compFactory = factory.componentFactories
               .find(x => x.componentType === DynamicHtmlComponent);
        const cmpRef = this.vcRef.createComponent(compFactory, 0);
        cmpRef.instance.prop = 'test';
        cmpRef.instance.outputChange.subscribe(()=>...);;
    });
  }
}

And then use it like:

<html-outlet [html]="article?.html">

Where html is path to article html

See more details in this Plunkr

Sign up to request clarification or add additional context in comments.

2 Comments

You are amazing! Thank you so much, this saved me a lot of trouble!
When attempting to use this, it is not parsing out as a htmlUrl but simply html. I copied over the exact piece from your plunkr.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.