Home > Net >  How can my template include an element whose type is determined by an expression in angularjs?
How can my template include an element whose type is determined by an expression in angularjs?

Time:11-19

It's 2022 and sadly I'm learning AngularJS (already past end of life!)

I need need to use what might be called a dynamic element/component. Pseudocode example:

In controller:

   this.theElementName = 'b';

In the template:

   <{{$ctrl.theElementName}}>this is some text</{{$ctrl.theElementName}}>

I would want this to create <b>this is some text</b>.

The reason is that I want to generate an array of different directives to render, and I don't want code like:

<b ng-if="$ctrl.theElementName === 'b'">this is some text</b>
<div ng-if="$ctrl.theElementName === 'div'">this is some text</div>
<directive-abc ng-if="$ctrl.theElementName === 'directive-abc'">this is some text</directive-abc>
...

In Svelte, it's

<svelte:element this={theElementName} />

In Vue it's

<div :is="theElementName" />

EDIT: in response to the reluctant 'that person', clarifying the use-case

Consider a user-configurable UI. The result of the configuration might be an array list of components desired. I would then need to loop and output those different components in my template. Of course the components would need a standard interface for properties passesd in, events emitted etc. but that can all be designed for.

My code could do a big switch statement, but that requires prior knowledge of every possible component that might be used now or in the future. By doing it the way I intend to, however, a future person could add a component without needing to touch this code.

CodePudding user response:

Not a brilliant solution, but documenting what is more of a workaround.

ng-include can be used to source another template file. That file can contain the component you need to include.

<ng-include src="'/path/to/'   theElementName   '.html'"></ng-include>

CodePudding user response:

You can write directive my-directive to use:

<div my-directive="$ctrl.theElementName">...

to generate:

<div><component-a>...
<div><component-b>...
<div><component-c>...

All directive should do is to generate html string and compile it:

element.append($compile('<'   scope.myDirective   '>...')(scope)) 

(also remember to update content in onChanges if you want to support it)

Directive may also copy certain/all attributes from original element etc.

P.S. you should be cautious e.g. if component name comes from database that may allow injections.

  • Related