How to watch Observable value on WhileSelected?

In my app, when you go to a mode that does destructive actions, like erasing data, certain colors turn red.

I have done this using an Observable mapping to two dictionaries.

Colors.js:

var defaultColors = {
    unselected: "#3283CE",
    selected: "#81C3FF"
}
var eraseColors = {
    unselected: "#B75743"
    selected: "#E67474"
}
module.exports = {
    defaultColors: defaultColors,
    eraseColors: eraseColors
};

Then I have a function in some other file that swaps the Observable’s value.

var theme = Observable(Colors.defaultColors)
function swapColors() {
    if (!swap) {
        theme.value = Colors.eraseColors
        swap = true
    } else {
        theme.value = Colors.defaultColors
        swap = false
    }
}

I now have a bunch of radio buttons on the screen that use an Attractor to smoothly change their (un)selected color:

<Attractor ux:Name="ColorAttractor" Target="Background.Color" Value="{colors.unselected}" Type="Easing" Duration="0.1" DurationExp="0" />

This works pretty great! When the mode is changed, the Attractor reacts and the color transitions. But now, I also want it to transition between a selected color as well.

<WhileSelected>
	<Change ColorAttractor.Value="{colors.selected}" />
</WhileSelected>

When the color scheme is set to the default one, and I select a radio button, it turns to {colors.selected}.
But, when I change the color scheme to eraseColors, every single button changes it’s background back to {colors.unselected}!
This is probably because the WhileSelected Event only triggers once and when the color scheme Observable is changed to eraseColors, the Change animator or WhileSelected Event doesn’t react again, making the Attractor’s Value change to the respective color scheme’s {colors.unselected}.

How could I make this work?

Could you please post a complete, minimal reproduction that one could copy & paste and run? It would be far easier to suggest the right solution if there was something to look at, aside tiny snippets.

Okay. Getting a zip file ready right now.

Here it is.
https://drive.google.com/open?id=0B4RPHNXGZ_K8ckFfTlN5bUl6VjA

To replicate the bug, select one of the buttons and then click “Change Colors”. The color will become {colors.unselected} again, but this time in the second color scheme. But if you click on the “previously selected” radio button, you have to double-click it to “reselect” it because it actually is still selected.

It seems like there’s another bug too, where the Attractor fades in the radio button background color when the application first starts (or when you reload), as opposed to just instantly showing up.

That fade doesn’t happen when I set it’s initial value to something like White instead of {colors.unselected}

Still looking into this. Pasting here a minimal reproduction (would have loved to get it in this form from you!) that still exhibits what you describe, just so that it doesn’t get lost.

Will post again when I have some updates.

<App Background="#222">
    <JavaScript>
    var Observable = require("FuseJS/Observable");

    var swap = Observable(true);
    var colors = swap.map(function(x) {
        if (x) {
            return {deselected: "#3283CE", selected: "#81C3FF"};
        } else {
            return {deselected: "#B75743", selected: "#E67474"};
        }
    });

    function swapColors() {
        swap.value = ! swap.value;
    }

    module.exports = {
        colors: colors,
        swapColors: swapColors
    };
    </JavaScript>

    <ClientPanel>
        <StackPanel Alignment="Center" ItemSpacing="12">

            <StackPanel Orientation="Horizontal" ItemSpacing="1">
                <Selection MaxCount="1" />
                <WSI.RadioButton ID="0" />
                <WSI.RadioButton ID="1" />
            </StackPanel>

            <Panel Alignment="Center">
                <Clicked>
                    <Callback Handler="{swapColors}" />
                </Clicked>
            	<Text Value="Change Colors" Alignment="Center" Color="White" Margin="12" />
            	<Rectangle Color="#fff2" CornerRadius="2" />
            </Panel>

        </StackPanel>
    </ClientPanel>

    <Panel Width="74" Height="56" ux:Class="WSI.RadioButton">
        <Rectangle ux:Name="bg" Layer="Background" CornerRadius="3" />

        <string ux:Property="ID" />
        <Selectable Value="{ReadProperty ID}" />

        <Attractor ux:Name="ColorAttractor" Target="bg.Color" Value="{colors.deselected}" Type="Easing" Duration="0.2" DurationExp="0" />

        <Clicked>
            <ToggleSelection />
        </Clicked>

        <WhileSelected>
            <Change ColorAttractor.Value="{colors.selected}" />
        </WhileSelected>
    </Panel>

</App>

Hi again,

so the problem apparently is that Attractor does not play nicely with Selection API and WhileSelected in particular when dealing with data-bound Observables. There is now a ticket that will be looked into.

There’s one more thing… we just found a somewhat hackish workaround that does exactly what you needed:

<App Background="#222">
    <JavaScript>
    var Observable = require("FuseJS/Observable");

    var swap = Observable(true);
    var colors = swap.map(function(x) {
        if (x) {
            return {deselected: "#3283CE", selected: "#81C3FF"};
        } else {
            return {deselected: "#B75743", selected: "#E67474"};
        }
    });

    function swapColors() {
        swap.value = ! swap.value;
    }

    module.exports = {
        colors: colors,
        swapColors: swapColors
    };
    </JavaScript>

    <ClientPanel>
        <StackPanel Alignment="Center" ItemSpacing="12">

            <StackPanel Orientation="Horizontal" ItemSpacing="1">
                <Selection MaxCount="1" />
                <WSI.RadioButton ID="0" />
                <WSI.RadioButton ID="1" />
            </StackPanel>

            <Panel Alignment="Center">
                <Clicked>
                    <Callback Handler="{swapColors}" />
                </Clicked>
            	<Text Value="Change Colors" Alignment="Center" Color="White" Margin="12" />
            	<Rectangle Color="#fff2" CornerRadius="2" />
            </Panel>

        </StackPanel>
    </ClientPanel>

    <Panel Width="74" Height="56" ux:Class="WSI.RadioButton">
        <Rectangle ux:Name="bg" Layer="Background" CornerRadius="3" />

        <string ux:Property="ID" />
        <Selectable Value="{ReadProperty ID}" />

        <Attractor ux:Name="ColorAttractor" Target="bg.Color" Value="{Property isSelected.Progress} == 1 ? {colors.selected} : {colors.deselected}" Type="Easing" Duration="0.2" DurationExp="0" />

        <Clicked>
            <ToggleSelection />
        </Clicked>

        <WhileSelected ux:Name="isSelected" />
    </Panel>

</App>

Hope this helps and thanks for reporting!

Thank you SO much!