Read Textinput values in javascript

I have a Each Iteration in UX, is an Observable array from a fetch call,
in the Each, i put two columns, the Label and value, the value is the TextInput, and outside of the Each
i have a button “Save”, after upgrade the values of TextInput manually, i press the “Save” button.
How i do to read all of the TextInput values in JavaScript to be able to create a json string.

Please show some code trying to image how the code looks will make it hard for us to help

<StackPanel ux:Name="spVerInfra">
   <Rectangle Height="4" Width="400" Fill="#000000" Alignment="Left"/>
   <Each Items="{listInfra}">
      <WrapPanel>
         <Text Value="{Descripcion}" Width="180"/>
         <TextInput Value="{CantidadActual}" Width="50"/>
         <TextInput Value="{EnUso}" Width = "50"/>
         <TextInput Value="{Adaptada}" Width = "50"/>
      </WrapPanel>
   </Each> 
   <Button ux:Name="btnGuardar" Text="Guardar" Clicked="{GuardarActual}"/>
</StackPanel>

{listInfra} is the Observable array filled with the FETCH result.

The idea is when i press the button “Guardar” it call the “GuardarActual” function
to create the json string, but i don’t know how iterate the controls to get the value
from each TextInput.

Man this is a hard one this is as far as I got:

function convertToObservables(data) {
	function loop(obj) {
		var newObj = {};
		for (var key in obj) {
			var val = obj[key];
			var type = typeof val;
			if (val instanceof Array) {
				newObj[key] = Observable(val).expand();
			} else if (type === 'string' || type === 'number') {
				newObj[key] = Observable(val);
			} else {
				newObj[key] = loop(val);
			}
		}
		return newObj;
	}
	return data.map(loop);
}

convertToObservables(data); // pass in the array of data

I’m not even sure if it works correctly, and trying to convert it back is hard, hopefully someone from the fuse team can help, I’m lost on this one.

Thank you for your answer Edwin, i will try your code.

Maybe i’m doing wrong in fuse because i’m working with web applications
and i trying to do the same.

thanks.

Guys, exactly what do you think you are you doing there?

Okay, let’s see if we can fix this for you… with a little walk-through of how I’d approach the challenge.

First off, you say you’re getting data from an API using fetch. That’s cool, and we even see that your data is an array, and that it contains objects that hold several properties, specifically Descripcion, CantidadActual, EnUso and Adaptada. I myself would prefer english names, but for the sake of an example, this floats our boat just fine.

So, here, let’s make some mock data, since we obviously don’t know how to get to your proprietary API:

	<JavaScript>
		var Observable = require('FuseJS/Observable');
		var dataFromFetch = [];

		function getData() {
			// in your case, you will likely have your .fetch() call here,
			// and then iterate over whatever you get in response,
			// and add objects to the dataFromFetch array
			for (var i = 0; i < 3; i++) {
				// we're just making some objects in a loop for test purposes here
				dataFromFetch.push(new SingleEntry('This is Descripcion #' + i + '!', 'This is CantidadActual #' + i + '!', 'This is EnUso #' + i + '!', 'This is Adaptada #' + i + '!'));
			}
		}

		// this here represents a single object in our dataFromFetch array
		function SingleEntry(descripcion, cantidadactual, enuso, adaptada) {
			this.descripcion = descripcion;
			this.cantidadactual = cantidadactual;
			this.enuso = enuso;
			this.adaptada = adaptada;
		};

		// on app init call getData()
		getData();

		module.exports = {
			'dataFromFetch': dataFromFetch
		};
	</JavaScript>

Now, that there obviously doesn’t do much since we don’t have any UX that would display the thing, so let’s add something simple for the layout part there:

	<StackPanel ItemSpacing="3" Margin="3" Background="#eee">
		<Each Items="{dataFromFetch}">
			<Panel>
				<StackPanel ItemSpacing="1" ClipToBounds="true">
					<TextInput Value="{descripcion}" />
					<TextInput Value="{cantidadactual}" />
					<TextInput Value="{enuso}" />
					<TextInput Value="{adaptada}" />
				</StackPanel>
				<Rectangle Fill="#fff" CornerRadius="3" />
			</Panel>
		</Each>
		<Panel Alignment="Center" Margin="10" Width="180">
			<Text Alignment="Center" Value="Guardar" Margin="10" />
			<Rectangle Fill="#fff" CornerRadius="3" />
		</Panel>
	</StackPanel>

So now what we have is a very basic data model, and the UI to show it. Sweet, what’s next?

Right, we want the Save button to call some function that does magic saving. Let’s add that function to both UX and JS, shall we?

		function guardarActual() {
		};
		
		module.exports = {
			'dataFromFetch': dataFromFetch,
			'guardarActual': guardarActual
		};
...
		<Panel Alignment="Center" Margin="10" Width="180" HitTestMode="LocalBoundsAndChildren">
			<Clicked>
				<Callback Handler="{guardarActual}" />
			</Clicked>
			<Text Alignment="Center" Value="Guardar" Margin="10" />
			<Rectangle Fill="#fff" CornerRadius="3" />
		</Panel>

So far so good, let’s make our saving function actually do something useful. It could, for example, look for the data that we need to save.

So where is the data, you ask? Exactly where we left it - in our dataFromFetch variable! So let’s just loop through it and build our resulting JSON array that we then stringify and get something you can use later:

		function guardarActual() {
			// the result we want to get is a JSON array, so let's start with an array here
			var res = [];
			for (var i in dataFromFetch) {
				// now, let's create an object for each object that we have in dataFromFetch,
				// with all respective properties, just like they were added there
				var tmp = {};
				tmp.descripcion = dataFromFetch[i].descripcion;
				tmp.cantidadactual = dataFromFetch[i].cantidadactual;
				tmp.enuso = dataFromFetch[i].enuso;
				tmp.adaptada = dataFromFetch[i].adaptada;
				// and now let's add our temporary object to res array
				res.push(tmp);
			}
			var jsonString = JSON.stringify(res);
			// hey, um... what do you want to do with the json string there? probably send to your backend, eh?
			console.log('This is what we got upon saving: ' + jsonString);
		};

At this point you will be looking at this and saying: “But hey! It doesn’t see the changes that I’m making in the TextInputs and when I click the Save button, it just flushes out whatever originally was there in the dataFromFetch variable!”

And you’re absolutely right (Obama too wasn’t born a president, he became one). So here, that’s because we’re currently not observing the changes made to any of those text values. Let’s fix that:

		function SingleEntry(descripcion, cantidadactual, enuso, adaptada) {
			this.descripcion = Observable(descripcion);
			this.cantidadactual = Observable(cantidadactual);
			this.enuso = Observable(enuso);
			this.adaptada = Observable(adaptada);
		};

Not only do we need to make them Observables, we also need to account for this change in the saving function, so let’s fix that one too (notice how we’re adding .value to all observable references!):

		function guardarActual() {
			// the result we want to get is a JSON array, so let's start with an array here
			var res = [];
			for (var i in dataFromFetch) {
				// now, let's create an object for each object that we have in dataFromFetch,
				// with all respective properties, just like they were added there
				var tmp = {};
				tmp.descripcion = dataFromFetch[i].descripcion.value;
				tmp.cantidadactual = dataFromFetch[i].cantidadactual.value;
				tmp.enuso = dataFromFetch[i].enuso.value;
				tmp.adaptada = dataFromFetch[i].adaptada.value;
				// and now let's add our temporary object to res array
				res.push(tmp);
			}
			var jsonString = JSON.stringify(res);
			// hey, um... what do you want to do with the json string there? probably send to your backend, eh?
			console.log('This is what we got upon saving: ' + jsonString);
		};

And now, my friends, every time you click that Save button, you’re getting everything just how it was entered.

Hope this helps! Here’s the full code for reference:

<App Background="#eee">
	<JavaScript>
		var Observable = require('FuseJS/Observable');
		var dataFromFetch = [];

		function getData() {
			// in your case, you will likely have your .fetch() call here,
			// and then iterate over whatever you get in response,
			// and add objects to the dataFromFetch array
			for (var i = 0; i < 3; i++) {
				// we're just making some objects in a loop for test purposes here
				dataFromFetch.push(new SingleEntry('This is Descripcion #' + i + '!', 'This is CantidadActual #' + i + '!', 'This is EnUso #' + i + '!', 'This is Adaptada #' + i + '!'));
			}
		}

		// this here represents a single object in our dataFromFetch array
		function SingleEntry(descripcion, cantidadactual, enuso, adaptada) {
			this.descripcion = Observable(descripcion);
			this.cantidadactual = Observable(cantidadactual);
			this.enuso = Observable(enuso);
			this.adaptada = Observable(adaptada);
		};


		function guardarActual() {
			// the result we want to get is a JSON array, so let's start with an array here
			var res = [];
			for (var i in dataFromFetch) {
				// now, let's create an object for each object that we have in dataFromFetch,
				// with all respective properties, just like they were added there
				var tmp = {};
				tmp.descripcion = dataFromFetch[i].descripcion.value;
				tmp.cantidadactual = dataFromFetch[i].cantidadactual.value;
				tmp.enuso = dataFromFetch[i].enuso.value;
				tmp.adaptada = dataFromFetch[i].adaptada.value;
				// and now let's add our temporary object to res array
				res.push(tmp);
			}
			var jsonString = JSON.stringify(res);
			// hey, um... what do you want to do with the json string there? probably send to your backend, eh?
			console.log('This is what we got upon saving: ' + jsonString);
		};
		
		// on app init call getData()
		getData();

		module.exports = {
			'dataFromFetch': dataFromFetch,
			'guardarActual': guardarActual
		};
	</JavaScript>

	<StackPanel ItemSpacing="3" Margin="3" Background="#eee">
		<Each Items="{dataFromFetch}">
			<Panel>
				<StackPanel ItemSpacing="1" ClipToBounds="true">
					<TextInput Value="{descripcion}" />
					<TextInput Value="{cantidadactual}" />
					<TextInput Value="{enuso}" />
					<TextInput Value="{adaptada}" />
				</StackPanel>
				<Rectangle Fill="#fff" CornerRadius="3" />
			</Panel>
		</Each>
		<Panel Alignment="Center" Margin="10" Width="180" HitTestMode="LocalBoundsAndChildren">
			<Clicked>
				<Callback Handler="{guardarActual}" />
			</Clicked>
			<Text Alignment="Center" Value="Guardar" Margin="10" />
			<Rectangle Fill="#fff" CornerRadius="3" />
		</Panel>
	</StackPanel>

</App>

Thank you UIdis your example was helpful to do what I looking for.

Cheers, mate!

All I can hope for is that the example not only helped you to solve the issue at hand, but also provided a better understanding of Observables overall. With some added tricks here and there :slight_smile:

Yes you right, I know now that the “Observable” is the key to many things.

A couple of months ago I made something with a json array from a storage file,
I used the Observable and the function to fill it (I saw it in a Fuse video)
but was a different solution not like I want to reach now.

Thanks again!!!