1

In one of the html files in an Angular13 application, I'm using an element that I'd like to supply the list of attributes and their values via the double-binding methods of Angular {{value of attribute}} so that a list of social media icons can be displayed.

For instance, instead of doing this hard-coding:

<!-- Twitter -->
<svg xmlns="http://www.w3.org/2000/svg"
     width="16"
     height="16"
     fill="cornflowerblue"
     class="bi bi-twitter"
     viewBox="0 0 16 16">
     <path d="M5.026 15c6.038 0 9.341-5.003 9.341-9.334 0-.14 0-.282-.006-.422A6.685 6.685 0 0 0 16 3.542a6.658 6.658 0 0 1-1.889.518 3.301 3.301 0 0 0 1.447-1.817 6.533 6.533 0 0 1-2.087.793A3.286 3.286 0 0 0 7.875 6.03a9.325 9.325 0 0 1-6.767-3.429 3.289 3.289 0 0 0 1.018 4.382A3.323 3.323 0 0 1 .64 6.575v.045a3.288 3.288 0 0 0 2.632 3.218 3.203 3.203 0 0 1-.865.115 3.23 3.23 0 0 1-.614-.057 3.283 3.283 0 0 0 3.067 2.277A6.588 6.588 0 0 1 .78 13.58a6.32 6.32 0 0 1-.78-.045A9.344 9.344 0 0 0 5.026 15z"/>
    </svg>

I'd like to do this instead:

    <svg xmlns="{{socBtn.xmlns}}"
      width="{{socBtn.width}}"
      height="{{socBtn.height}}"
      fill="{{socBtn.fill}}"
      class="{{socBtn.clss}}"
      viewBox="{{socBtn.viewBox}}">
      <path d="{{socBtn.pathD}}"/>
    </svg>

but I keep getting the following error message:

error NG8002: Can't bind to 'xmlns' since it isn't a known property of ':svg:svg'. xmlns="{{socBtn.xmlns}}"

I created a model interface for the list of Social Buttons that I want to display like this:

    export interface SocialButton {
      btnName: String;
      href: String;
      xmlns: String;
      width: number;
      height: number;
      fill: String;
      clss: String;
      viewBox: String;
      pathD: String;
    }

And I'm reading those values from a JSON data file. All of that works as expected and I'm able to display the contents of the social buttons that I want to display by using a simple *ngFor loop:

    <ul>
        <li *ngFor="let socBtn of socBtns">
            <a  class="ml-2 {{socBtn.clss}}"
                target="_blank"
                href="{{socBtn.href}}"
                title="{{socBtn.btnName}}">

            {{socBtn.btnName}}
        </a>
        <ul>
            <li>class: {{socBtn.clss}}</li>
            <li>href:  {{socBtn.href}}</li>
            <li></li>
            <li>svg.xmlns:   {{socBtn.xmlns}}</li>
            <li>svg.height:  {{socBtn.height}}</li>
            <li>svg.width:   {{socBtn.width}}</li>
            <li>svg.viewBox: {{socBtn.viewBox}}</li>
            <li>svg.fill:    {{socBtn.fill}}</li>
            <li></li>
            <li>Full Strings:</li>
            <li>svg {{ socBtnSvgs[i] }}</li>
            <li>path {{socBtnPths[i]}}</li>
        </ul>
    </li>
</ul>

The loop outputs the following for the Twitter social button:

  • Twitter
    • class: bi bi-twitter
    • svg.height: 16
    • svg.width: 16
    • svg.viewBox: 0 0 16 16
    • svg.fill: cornflowerblue
    • Full Strings:
    • xmlns="http://www.w3.org/2000/svg" width="16" height="16" class="bi bi-twitter" o fill="cornflowerblue" viewBox="0 0 16 16"
    • "M5.026 15c6.038 0 9.341-5.003 9.341-9.334 0-.14 0-.282-.006-.422A6.685 6.685 0 0 0 16 3.542a6.658 6.658 0 0 1-1.889.518 3.301 3.301 0 0 0 1.447-1.817 6.533 6.533 0 0 1-2.087.793A3.286 3.286 0 0 0 7.875 6.03a9.325 9.325 0 0 1-6.767-3.429 3.289 3.289 0 0 0 1.018 4.382A3.323 3.323 0 0 1 .64 6.575v.045a3.288 3.288 0 0 0 2.632 3.218 3.203 3.203 0 0 1-.865.115 3.23 3.23 0 0 1-.614-.057 3.283 3.283 0 0 0 3.067 2.277A6.588 6.588 0 0 1 .78 13.58a6.32 6.32 0 0 1-.78-.045A9.344 9.344 0 0 0 5.026 15z"

As one can see, I also tried combining all of the attributes into two long strings, socBtnSvgs[i] and socBtnPths[i], so that I could then use them this way:

            <svg {{ socBtnSvgs[i] }}>
                <path d={{ socBtn.pathD[i] }}/>
            </svg>

That doesn't generate output and the following error appears in the developers window:

    ERROR DOMException: Failed to execute 'setAttribute' on 'Element': '{{' is not a valid attribute name.

And when I change it to just use the variable name without the double braces like this:

            <svg "socBtnSvgs[i]">
                <path d="socBtnPths[i]"/>
            </svg>

it generates an error as well. I then tried using the <use> statement so that I could isolate the path statement and eliminate the double braces:

            <svg>
                <use xlink:xlink="socBtnSvgs[i]"/>
                <path d="socBtnPths[i]"/>
            </svg>

but that still generates an error, although a more encouraging one:

platform-browser.mjs:605 Error: attribute d: Expected moveto path command ('M' or 'm'), "socBtnPths[i]".

I found this more encouraging although what it was complaining about (that it expected an 'M', moveto path command) is, in fact, included in the contents of the socBtnPths[0] variable ("M5.026 15c6 ... ").

So, I'm at a loss as to what try next. Any ideas on how I can use these values with the svg element?

wmm2
  • 11
  • 2

1 Answers1

0

The duplicate reference provided was helpful: I solved the problem by preceding each attribute definition with the attr keyword and enclosing it in square brackets, i.e. [attr.xmlns]="socBtn.xmls".

Here's the end result:

            <svg
                 [attr.xmlns]="socBtn.xmlns"
                 [attr.width]="socBtn.width"
                 [attr.height]="socBtn.height"
                 [attr.fill]="socBtn.fill"
                 [attr.class]="socBtn.clss"
                 [attr.viewBox]="socBtn.viewBox">
                <path [attr.d]="socBtn.pathD"/>
            </svg>

Thank you sooooo much!

wmm2
  • 11
  • 2