3

I am doing something that I think is relatively straight forward, but Angular is not working out correctly for me. I am pretty sure this can be done I think I am just missing something here.

Essentially I have made a form service in Angular where I can define an array of objects for making forms on the fly. An example of that would as follows:

email: [
    {
        name: 'email',
        type: text,
        required: true
    }
]

This could represent a form that someone would enter their email in. What I would like to do is run an ng-repeat over this and add in some Angular dirty checking like so:

<form name="form">
    <span ng-repeat="fields in formFields">
        <input name="{{field.name}}
            ng-model="user[field.name]" />


       <div ng-show="form.{{field.name}}.$dirty">Input is dirty</div>
    </span>
</form>

However this is not working for some reason. I have tried a few different combinations to make this work but no luck. I am following the examples I am seeing on the Angular docs here: https://docs.angularjs.org/guide/forms

Here is a fiddle with the current code: http://jsfiddle.net/HB7LU/4764/ ... As you can see the two way binding is working in the ng-repeat but not the dirty checking. The dirty checking is working in the example before.

What am I doing wrong here?

Sethen
  • 11,140
  • 6
  • 34
  • 65
  • Which one of the six examples in the docs page? – cheekybastard Jul 04 '14 at 00:49
  • @cheekybastard The section Binding to form and control state is where I was looking. – Sethen Jul 04 '14 at 00:50
  • 1
    Have a look at my previous answers on accessing dynamic form elements in Angular: http://stackoverflow.com/questions/24020503/angular-ng-repeat-with-ng-form-accessing-validation-in-controller/24050297#24050297 and http://stackoverflow.com/questions/24071422/set-angularjs-input-directive-name-as-a-variable/24071758#24071758 Basically, you can't use interpolation to name dynamic input elements - you'll need to create a directive to work around this. – Sly_cardinal Jul 04 '14 at 00:51
  • An update on my previous comment - that refers to Angular 1.2. In Angular 1.3+ you **can** use {{interpolation}} to dynamically name inputs. – Sly_cardinal Dec 27 '15 at 13:04

1 Answers1

7

You can add <span ngForm="myForm"> to handle this.

It will work with multiple input elements, but see the note at the end.

Here is an updated fiddle showing this solution: http://jsfiddle.net/HB7LU/4766/

<div ng-controller="MyCtrl">
    <form name="form">  
        <input name='myInput' ng-model='model.myInput'>
        <div ng-show='form.myInput.$dirty'>Dirty</div>

        <!-- 1. Add `ng-form="myForm"` directive. -->
        <span ng-form="myForm"
              ng-repeat='field in email'>
            <input ng-model="field[email.name]" name={{email.name}} />
            {{field[email.name]}}

            <!-- 2. Reference the named parent -> `myForm.$dirty` -->
            <div ng-show="myForm.$dirty">It's dirty!</div>
        </span>
    </form>
</div>

Note that you will end up with a single myForm instance from form.myForm - if you need to access individual myForm instances from form you will need to use a custom directive to handle this (see my comment on your question).

Sly_cardinal
  • 12,270
  • 5
  • 49
  • 50