Each class: Change item values from UX

I have spent time trying to figure out this by looking through docs, examples and other threads, but so far haven’t been able to find what I am looking for. I need a way to affect an item in an object array that is called from a ux Each class. Here are several questions i have, answers to any of which I think would solve my problem:

  1. How can I call a function from within my UX and pass a value to it as a parameter? (I could store { item: } inside the array and pass it to a function using a callback)
  1. Can i use toggle control to affect a value of an object stored in the Each item being referenced? In this example below the toggle control works, and the properly executes, but as you can see from the debug that the value in the “Items” object has not changed.
  1. Can i access the item being used in Each directly, and use a Set, Change, or javascript to affect a value in the object being looped through?
  1. Normally using an Observable variable would allow you to change values of variables from the UX. How do you create an Observable array?

Here is some code I wrote that demonstrates what something like this would look like. I want to figure out how to adjust this code in order to toggle the boolean value of “happy” stored in “items” when clicked on. Clicking on the items should affect the “items” variable, which would mean that printHappyTotal()'s console output would change, and the text output of {happy} would also be affected.

<App Background="#222">
	<JavaScript>
		var items = [
			{ name: "Jake", happy: false },
            { name: "Julie", happy: true },
            { name: "James", happy: true },
            { name: "Justin", happy: false },
            { name: "Joseph", happy: true },
            { name: "Josie", happy: true },
            { name: "Jessica", happy: true },
            { name: "Jacob", happy: false },
            { name: "Jake", happy: true },
            { name: "Jennifer", happy: false },
            { name: "Jerry", happy: true },
            { name: "Jerad", happy: false }
		]

	    function printHappyTotal(){
	    	var numHappy = 0;
	    	for (var i = 0; i < items.length; i++) {
	    		if (items[i].happy) { numHappy++ }
	    	}
	    	console.log(numHappy + "/" + items.length + " people are happy.")
	    }

	    module.exports = {
	        items: items,
	        printHappyTotal: printHappyTotal
	    };
	</JavaScript>

	<ScrollView>
		<StackPanel>
		    <Each Items="{items}">
		    	<Rectangle CornerRadius="10" Margin="5" Height="100" Color="#444">
		    		<ToggleControl>
						<Clicked>
							<Toggle Target="{happy.value}"/>
							<Callback Handler="{printHappyTotal}"/>
						</Clicked>

						<Panel ux:Name="Fade" Margin="2" Color="#000" Opacity="{happy} ? 0 : 0.2"/>

						<WhileTrue>
							<Change Fade.Opacity="{happy} ? 0.2 : 0" Duration="0.2" Easing="QuadraticInOut" />
						</WhileTrue>
					</ToggleControl>
	            	<StackPanel Alignment="Center">
	            		<Text FontSize="25" TextColor="#fff" Value="{name}" />
	            		<Text FontSize="15" TextAlignment="Center" TextColor="#fff" Value="Happy: {happy}" />
	            	</StackPanel>
	            </Rectangle>
		    </Each>
		</StackPanel>
	</ScrollView>
</App>

Thanks for your help!

Hi Graeme,

your questions show that you have not thoroughly understood the concept of Observables in Fuse. I suggest you carefully read this section of the docs, because it covers everything you’ve asked: https://www.fusetools.com/docs/fusejs/observable

Now let’s answer your questions:

How can I call a function from within my UX and pass a value to it as a parameter? (I could store { item: } inside the array and pass it to a function using a callback)

Answer: You don’t [need to]. If you call a function from Clicked on an item from within an Each, it automatically passes the data context of that item to the function arguments.

Can i use toggle control to affect a value of an object stored in the Each item being referenced? In this example below the toggle control works, and the properly executes, but as you can see from the debug that the value in the “Items” object has not changed.

Answer: Yes, you can. But not the way you did it. Toggle is meant to be used on a UX-toggle, such as a WhileTrue, which then can be data-bound to an observable boolean in JavaScript.

Can i access the item being used in Each directly, and use a Set, Change, or javascript to affect a value in the object being looped through?

Answer: Again, yes. Change and Set are usually applied to UX transformations, while changing values usually happens via JavaScript callbacks.

Normally using an Observable variable would allow you to change values of variables from the UX. How do you create an Observable array?

Answer: Any Observable is an array in the sense you’re asking. Single-value observables differ from multi-value observable only with that they hold a single value.

Here is your code, adjusted to achieve what you were asking for:

<App Background="#222">
    <JavaScript>
    	var Observable = require("FuseJS/Observable");
        var items = [
            { name: "Jake", happy: Observable(false) },
            { name: "Julie", happy: Observable(true) },
            { name: "James", happy: Observable(true) },
            { name: "Justin", happy: Observable(false) },
            { name: "Joseph", happy: Observable(true) },
            { name: "Josie", happy: Observable(true) },
            { name: "Jessica", happy: Observable(true) },
            { name: "Jacob", happy: Observable(false) },
            { name: "John", happy: Observable(true) },
            { name: "Jennifer", happy: Observable(false) },
            { name: "Jerry", happy: Observable(true) },
            { name: "Jerad", happy: Observable(false) }
        ]

        function printHappyTotal(args){
        	console.log("clicked item data context: " + JSON.stringify(args));
            var numHappy = 0;
            items.forEach(function(i) {
            	if (i.name == args.data.name) {
            		i.happy.value = ! i.happy.value;
            	}
            	if (i.happy.value) {
            		numHappy++;
            	}
            });
            console.log(numHappy + "/" + items.length + " people are happy.")
        }

        module.exports = {
            items: items,
            printHappyTotal: printHappyTotal
        };
    </JavaScript>

    <ScrollView>
        <StackPanel>
            <Each Items="{items}">
                <Rectangle CornerRadius="10" Margin="5" Height="100" Color="#444">
                    <ToggleControl>
                        <Clicked>
                            <Callback Handler="{printHappyTotal}"/>
                        </Clicked>

                        <Panel ux:Name="Fade" Margin="2" Color="#000" Opacity="{happy} ? 0 : 0.2"/>

                        <WhileTrue>
                            <Change Fade.Opacity="{happy} ? 0.2 : 0" Duration="0.2" Easing="QuadraticInOut" />
                        </WhileTrue>
                    </ToggleControl>
                    <StackPanel Alignment="Center">
                        <Text FontSize="25" TextColor="#fff" Value="{name}" />
                        <Text FontSize="15" TextAlignment="Center" TextColor="#fff" Value="Happy: {happy}" />
                    </StackPanel>
                </Rectangle>
            </Each>
        </StackPanel>
    </ScrollView>
</App>

Thank you for your thorough response. It helped me understand what I was doing wrong in my project. I also made sure to read the Observable page again. Thanks Uldis!