13

Given a data structure that contains an array of JavaScript objects, how can I bind a certain entry from that array to an input field using Angular?

The data structure looks like this:

$scope.data = {
    name: 'Foo Bar',
    fields: [
        {field: "F1", value: "1F"},
        {field: "F2", value: "2F"},
        {field: "F3", value: "3F"}
    ]
};

The fields array contains several instances of the given structure, with each entry having both a field attribute and a value attribute.

How can I bind an input control to the value field attribute of the array entry with the field F1?

<input ng-model="???"/>

I know that I could bind all fields using an ng-repeat, but that's not what I want. The above data is just an example from a much larger list of fields, where I only want to bind a pre-defined subset of fields to controls on the screen. The subset is not based on the attributes in the array entries, but is known at design time of the page.

So for the above example, I would try to bind F1 to one input on the page, and F2 to another one. F3 would not be bound to a control.

I've seen examples where a function was used in the ng-model, but it doesn't seem to work with Angular 1.1.0.

Is there another clever way to bind the input field to a specific array entry?

Here's a fiddle that has an example, but does not work since it's trying to use function in the ng-model attribute: http://jsfiddle.net/nwinkler/cbnAU/4/

Update

Based on the recommendation below, this is what it should look like: http://jsfiddle.net/nwinkler/cbnAU/7/

3 Answers 3

12

I personally would reorganize the array in a way that field property of an entry of the array become the identifier of the object. Mhhh that sentence may sound strange. What I mean is the following:

$scope.data = {
    name: 'F1',
    fields: {
        F1: {
           value: "1F"
        },
        F2: {
           value: "2F"
        }
    }
};

If you want to bind a the value dynamically and it's an easy and quick way to achieve it. Here is your fiddle modified so that it words. http://jsfiddle.net/RZFm6/

I hope that helps

Sign up to request clarification or add additional context in comments.

4 Comments

Yes, reorganizing the array to a better structure is what I thought about as well. I'm not sure whether that's possible, since we receive the JSON from a backend service. I'll have to ask them whether they change the structure.
@nwinkler If you change the underlying model often it anyway makes sense to preprocess the array (within your controller) once before you bind it because with your current structure you would need to search the array every time you bind a new model. With reorganizing you loop once through the object and you are done. If they change the API for you it's even better :)
Accepted this answer since I think that's the right way to do it. We'll look into changing the format of the data and using it like you described.
@nwinkler Its the wrong way to change the Server json to fullfill the clients UI needs. For this you have to create viewmodels from the server json. And you you get additional clients to support which want to display the data in another way you want to change the server json again?
8

You can use an array of objects, just not an array of strings.

HTML:

<div ng-repeat="field in data.fields">
    <input ng-model="field.val"/>
</div>

JS:

$scope.data = {
    name: 'F1',
    fields: [
        { val: "v1" },
        { val: "v2" }
    ]
};

I've updated @Flek's fiddle here: http://jsfiddle.net/RZFm6/6/

Edit: Sorry just read your question properly, you can still use an array with:

<label>Bound to F1:</label>
<input ng-model="data.fields[0].value"/>

though maybe stop and think. Is there going to be variable number of fields ? or are you making a predetermined number of fields ? Use an array in the former and an object for the latter.

1 Comment

Worth noting here is that if you try and model fields[1] without having a fields[0] position, angularJS will interpret it as a Map. This might conflict with a Spring controller expecting an array. It's really hard to miss since "fields[0]" can be interpreted as both an array pos and a map pos.
3

One way to do it is to simply add the necessary references to the scope, like this:

$scope.fieldF1 = fieldValue('F1');
$scope.fieldF2 = fieldValue('F2');

And then use those references:

<input ng-model="fieldF1.value"/>
<input ng-model="fieldF2.value"/>

Fiddle: http://jsfiddle.net/cbnAU/5/

Note: I'm assuming that $scope.data is static, but if it happens to be dynamic you can always watch for changes on it and recalculate the references...

1 Comment

The data is dynamic (received from a backend service), and it's going to contain a huge list of fields. What you suggest works, but is not practical for our use case.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.