Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modify svg xlink:href through knockout attr binding

I can modify xlink:href through javascript and jquery just fine but modifying just the dom's xlink:href through the knockout attr binding does not work.

This is my svg definition

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="display:none">
<defs>
    <symbol id="icon-home" viewBox="0 0 32 32">
        <path class="path1" d="M32 18.451l-16-12.42-16 12.42v-5.064l16-12.42 16 12.42zM28 18v12h-8v-8h-8v8h-8v-12l12-9z"></path>
    </symbol>
</defs>

This is inserted at the top of the body

Then use knockout with html and the property icon on my view model

<svg class="svg-icon">
    <use id="myuse" data-bind="attr: {'xlink:href': icon }"></use>
</svg>

I am sure icon is returning correctly because I get the following rendered output

<svg class="svg-icon">
    <use data-bind="attr: {'xlink:href': icon }" xlink:href="#icon-home"></use>
</svg>

Which is correct, but nothing shows up. Does anyone have a working solution to this with knockout?

like image 381
nano2nd Avatar asked Dec 02 '22 19:12

nano2nd


1 Answers

As it seems, SVG will not update on DOM's modification.

So basically what you need to do is remove the SVG, update the fields, and add the SVG markup again.

This can be emulated with an if binding:

<!-- ko if: showSvg -->
<svg class="svg-icon">
    <use data-bind="attr: {'xlink:href': icon }"></use>
</svg>
<!-- /ko -->

When showSvg becomes false, your SVG will be removed from the DOM, and added again when it becomes true.

You would do:

myModel.showSvg(false);
myModel.icon("whatever");
myModel.showSvg(true);

Or more ko compliant, use a writeable computed to encapsulate this behaviour:

myModel.iconComp = ko.computed({
    read: myModel.icon,
    write: function (value) {
        myModel.showSvg(false);
        myModel.icon(value);
        myModel.showSvg(true);
    },
    owner: this
});

And use iconComp in your markup instead of icon.

UPDATE

Ok, forget everything I said...

It works if you define your attribute first (tested with last Chrome and IE):

<svg class="svg-icon">
    <use data-bind="attr:{ 'xlink:href': icon }" xlink:href=''></use>
    <!-- Add the attr you want to bind to, set it blank like this for example-->
</svg>

Then do your normal binding.

Demo

like image 74
GôTô Avatar answered Dec 28 '22 09:12

GôTô