Pregunta

When I try to use form.$setPristine from TypeScript, it doesn't work and the debug says form is undefined. According to what I read, $scope.formName.$setPristine() shall set the form to pristine. To access $scope.formName from the controller, I added it to my custom scope interface as an ng.IFormController property. However, when I call $scope.form.$setPristine(), it doesn't work, and debug shows $scope.form is undefined.

TypeScript:

interface IMyScope extends ng.IScope {
    employees: Array<IEmployee>;
    employeeToAdd: IEmployee;
    addEmployee(): void;
    form: ng.IFormController;
}

class EmployeeAddController {
    static $inject = ['$scope', 'Employees'];

    constructor(
        $scope: IMyScope,
        $modalInstance: ng.ui.bootstrap.IModalServiceInstance,  
        Employees: IUpdateableResourceClass<IUpdateableResource>
    ) {
        $scope.employees = new Array<IEmployee>();

        $scope.employeeToAdd = {
            Name: '',
            Email: ''
        };

        $scope.addEmployee = function () {
            Employees.save(null, $scope.employeeToAdd, function (employee: IEmployee) {
                $scope.employees.push(employee);
                $scope.employeeToAdd.Email = '';
            $scope.employeeToAdd.Name = '';
                $scope.form.$setPristine(); // $scope.form is undefined
            });
        };
    }
} 

HTML:

<form role="form" class="form-inline" name="form">
    <div class="form-group" ng-class="{ 'has-error': form.name.$dirty && form.name.$invalid }">
        <input type="text" class="form-control" ng-model="employeeToAdd.Name" name="name" required>
    </div>
    <div class="form-group" ng-class="{ 'has-error': form.email.$dirty && form.email.$invalid }">
        <input type="email" class="form-control" ng-model="employeeToAdd.Email" name="email" required>
    </div>
    <button type="button" class="btn btn-default" ng-click="addEmployee()" ng-disabled="form.$invalid">Add</button>
</form>
¿Fue útil?

Solución 2

Although Sobieck00's solution works as well, thanks to stevuu's suggestion, I have debugged it and found a way to do it without having to pass the form reference. form can be accessed as $scope.$$childTail.form:

interface IMyScope extends ng.IScope {
    employees: Array<IEmployee>;
    employeeToAdd: IEmployee;
    addEmployee(): void;
    $$childTail: any; // Add this to access $$childTail in current scope
}

Then in $scope.addEmployee() reset it with:

$scope.$$childTail.form.$setPristine();

Otros consejos

What I have done in my application with form is to pass the form object into the method that clears it instead of working off the scope directly.

<button data-ng-click="clearAndResetForm(Form)"></button>

$scope.clearAndResetForm = (form:ng.IFormController)=> {
   this.clearAndResetForm(form);
};


private clearAndResetForm(form:ng.IFormController) {
   this.$scope.fieldOne = undefined;
   this.$scope.fieldTwo = undefined;
   form.$setPristine();
}

I'm not entirely sure why my code would work while yours doesn't. But hopefully this approach might help you.

I had a similar problem and the problem occurred because the <form> tags were in the view rather than the template. For example;

<!-- This was in the template -->
<div class='container-fluid body-content'>
    <ng-view>

    </ng-view>
</div>

<!-- And this was in the view -->
<form id="frmSection" name="frmSection" role="form" class="form" novalidate>
  .
  .
  .
</form>  

Once I changed this to;

<-- Template -->
<div class="container-fluid body-content">
  <form id="frmSection" name="frmSection" role="form" class="form" novalidate>
    <ng-view>

    </ng-view>
  </form>
</div>

<-- View -->
<fieldset>
     <legend>Report Text</legend>

    <div class="form-group">
      .
      .
      .
    </div>
</fieldset>

The line $scope.frmSection.$setPristine(); worked as expected.

The other answers may work but it seems they are overcomplicating things. If you use "controller as", you can just give the form a name based on the alias and be done with it.

Take a look at the following example. I just name the form as a property on my controller, and then as you can see from the JavaScript I can reference it directly by name. No tricks, gimmicks, or strange work arounds and no need to rely on $scope.

(function (app) {
    
    function ctrl() {
    }
    
    angular.extend(ctrl.prototype, {
        email: '',
        submit: function () {
            if (this.ctrlForm.email.$invalid) {
                alert("Invalid email!");
                return;
            }
            alert("Submitted " + this.email);
            this.email = '';
            this.ctrlForm.$setPristine();
        }
    });
    
    app.controller("formCtrl", ctrl);
    
})(angular.module("formExample",[]));
<script src="https://code.angularjs.org/1.3.9/angular.min.js"></script>
<div ng-app="formExample" ng-controller="formCtrl as ctrl">
    <form name="ctrl.ctrlForm" role="form" novalidate="">
        <input name="email" type="email" required="" ng-model="ctrl.email" placeholder="Enter a valid email."/> 
        <div ng-if="ctrl.ctrlForm.email.$invalid">Email is invalid!</div> 
        <button ng-click="ctrl.submit()" ng-disabled="ctrl.ctrlForm.$invalid || ctrl.ctrlForm.$pristine">Submit</button>
    </form>
</div>

Note that formCtrl is the name I register the controller with, and ctrl is the alias for my controller (some people might prefer vm, so I name the form ctrl.ctrlForm. That is how I reference it in the HTML. The controller then gets that property, so it is referenced simply as this.ctrlForm.

Also as a fiddle: http://jsfiddle.net/jeremylikness/du5ptxyc/

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top