Cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

How do I modify a combo-button's icon via JavaScript?

ANSWERED

I want to change the combo-button-icon and combo-button-icon-press on a combo-button via JavaScript. The icon in the button should reflect a state of something in my app, so I need to change it programmatically. How can I do this?

 

This seems like something that should be in the "Interacting with Elements" section of https://dev.fitbit.com/guides/user-interface/javascript/

Best Answer
0 Votes
1 BEST ANSWER

Accepted Solutions

I just tested it here, it's working.

<svg>
<!-- TOP LEFT -->
<use id="btn-tl" href="#combo-button-upper-left" fill="fb-cyan">
<set href="combo-button-icon" attributeName="href" to="cog.png"/>
<set href="combo-button-icon-press" attributeName="href" to="cog_press.png"/>
</use>
</svg>
import document from "document";
let btn = document.getElementById("btn-tl");
let icon = btn.getElementById("combo-button-icon");
let icon_press = btn.getElementById("combo-button-icon-press");
console.log(icon.image);
console.log(icon_press.image);

icon.image = "cog_press.png"

View best answer in original post

Best Answer
8 REPLIES 8

You can get a handle on the button using getElementById, then use that to get a handle of each image.

 

Something like this: (untested).

 

let myButton = document.getElementById("myButton");
let press = myButton.getElementById("combo-button-icon-press");
press.image = "another.png";
Best Answer
0 Votes

I tried two different approaches, but no luck.

 

<use id="btnPlayPause" href="#combo-button-lower-right" fill="fb-white">
    <set id="btnPlayPause-icon" href="combo-button-icon" attributeName="href" to="play.png"/>
    <set id="btnPlayPause-icon-press" href="combo-button-icon-press" attributeName="href" to="play-press.png"/>
    <set href="combo-button-stroke" attributeName="display" to="inline"/>
</use>

I tried:

let btnPlayPause = document.getElementById("btnPlayPause");
btnPlayPause.getElementById('btnPlayPause-icon').attributes.to = 'pause.png';

and

document.getElementById('btnPlayPause-icon').attributes.to = 'pause.png';

No luck. Error in the console:

Unhandled TypeError: Cannot read property 'attributes' of null
Best Answer
0 Votes

Looks like JonFitbit code should work.
Alternative workaround:

I used two buttons in the same position, with different names. Displaying the one that I want. Unfortunately the “enabled” property does not work, but if you play with the display you can replicate it.

check this post:

https://community.fitbit.com/t5/SDK-Development/Combo-button-weird-behavior/td-p/2293224/jump-to/fir...

Best Answer

@agsurf5 wrote:
Unfortunately the “enabled” property does not work,

I spent *hours* learning this the hard way. Hey Fitbit, if something is broken, don't document it as working.

 

Best Answer

@JonFitbit's example didn't seem like it would work, which is why I tried something similar but slightly different in my post above. Based on what @agsurf5 said, I figured I should try it explicitly anyway. The result:

 

Unhandled TypeError: Cannot set property 'image' of null

 

Here's the code:

index.gui:

<use id="btnPlayPause" href="#combo-button-lower-right" fill="fb-white">
    <set id="btnPlayPause-icon" href="combo-button-icon" attributeName="href" to="play.png"/>
    <set id="btnPlayPause-icon-press" href="combo-button-icon-press" attributeName="href" to="play-press.png"/>
    <set href="combo-button-stroke" attributeName="display" to="inline"/>
</use>

app/index.js:

let btnPlayPause = document.getElementById("btnPlayPause");
let innerButtonImage = btnPlayPause.getElementById('btnPlayPause-icon');
innerButtonImage.image = "pause.png";

 

Best Answer
0 Votes

I should explain a little more why I didn't think Jon's approach would work: My understanding is that a <use> references a template symbol and the <set> child nodes are for modifying the attributes of the template symbol—they are not elements themselves within that template symbol. This is why I tried giving the <set> child nodes an id and trying to change their attributes, but changing their attributes does not seem to update the attributes of the template symbol instance after instantiation.

Best Answer
0 Votes

I just tested it here, it's working.

<svg>
<!-- TOP LEFT -->
<use id="btn-tl" href="#combo-button-upper-left" fill="fb-cyan">
<set href="combo-button-icon" attributeName="href" to="cog.png"/>
<set href="combo-button-icon-press" attributeName="href" to="cog_press.png"/>
</use>
</svg>
import document from "document";
let btn = document.getElementById("btn-tl");
let icon = btn.getElementById("combo-button-icon");
let icon_press = btn.getElementById("combo-button-icon-press");
console.log(icon.image);
console.log(icon_press.image);

icon.image = "cog_press.png"
Best Answer

Thank you, @JonFitbit! It worked. Clearly, I misunderstood how DOM selection differs in SVG from HTML and must have flubbed something when I tried what you originally posted.

 

Is the DOM of the components inspectable? I might have realized this sooner. If not, it might be useful to others to have the relevant parts documented.

Best Answer