2
@Directive({
    selector: "ng-template[model]",
    standalone: false,
})
export class ViewSelector {
    @Input() get model() { return this._model; }
    set model(value: Object) {
        ...
    }

    @Input("class") set classes(value: string) {
        ...
    }

I'm using this to instantiate views:

<ng-template [model]="model" class="foo bar"></ng-template>

In Angular 11, my directive would get both the 'model' and 'class' inputs, and I would use the class input to copy the class list to the instantated view, without introducing any additional DOM nodes (which complicates styling).

In Angular 19, the class attribute is never hit.

If I change the name to "custom-class" it's hit.

If I change the template code to:

<ng-template [model]="model" [class]="'foo bar'"></ng-template>

It's hit.

But this would require changing a lot of code in the system, and it's less intuitive for developers. The idea is that I can style the node that will be instantiated, using the same syntax as any other node.

Is there a way to restore the old behavior in Angular 19?

1 Answer 1

1

You can't have element attributes on an <ng-template>, because it doesn't map to an actual DOM element (well, you can add custom attributes and read them with @Attribute, but usual element attributes such as class, style etc. are ignored).

So, use template variables instead.

The only very unsafe and highly unrecommendable way is to dig out those attributes from directive's internal property _declarationTContainer, which contains attributes, but in a very different format (it seems that attributes are replaced by numbers: [1, 'foo', 'bar', 3, 'model'], and everything is given in an array, so maybe you could merge numbers with strings: { '1': 'foo bar', '3': 'model' } which might make more sense).

not recommended:

  constructor(private templateRef: TemplateRef<any>) {
    const internal: any = this.templateRef;

    const tContainer = internal?._declarationTContainer;
    const attrs: any[] = tContainer?.attrs;
    console.log('attrs', attrs);

    // [1, 'foo', 'bar', 3, 'model']

    // now you could construct an object
    //  to merge numbers with strings into
    // { '1': 'foo bar', '3': 'model' }
    // and then key that does not contain 'model' is your class attribute
    // (provided all your directives are in the same form)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.