Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to access $error from nested forms

Tags:

angularjs

I have one main form and another subForm. How I can access $error of the child form but without having to directly reference the subForm name?

I want to be able to display that name is required(for example) instead of just knowing the name of the form.

Here's a demo of my problem: http://plnkr.co/edit/QWZArI1UFPpJdjoK8eVn?p=preview

like image 747
Diego Plentz Avatar asked May 28 '14 21:05

Diego Plentz


2 Answers

Ok, I wasn't 100% sure I understood your question, but I think I do, so here's a stab at it:

There are a couple ways to access the errors of a child form, but all seem to need the name of the ngForm.

Assuming this structure:

<form name="parentForm">
  <ng-form name="childForm"></ng-form>
</form>

you know that you can access it via $scope.childForm.$error, but less known is that it is also attached to the parent form. You can access it with $scope.parentForm.childForm.$error, but obviously, that's no good, since you still need the name.

You could get hacky and loop through the properties on the parent form and try to tell which one is the child form and go from there.

Lastly, as we've discussed on Twitter/GitHub, I have a directive that kinda does some of this magic for you. It did have a bug that didn't handle embedded forms correctly, but I fixed it. Check out the new version of my directive that tries to simplify handling errors with Angular:

https://github.com/CWSpear/angular-form-errors-directive

I added the ability to display all the errors of all the child ngForms with a flag in v1.3.0.

like image 66
CWSpear Avatar answered Oct 12 '22 07:10

CWSpear


I think for this particular use case, my simple getErrors method on the scope is a more robust solution than the formErrors directive proposed in the accepted answer. Have a look at this comparison of the two solutions. The formErrors directive will clear errors from the child forms if the bottom child form is filled out. Play around with data entry and you will quickly see other bugs.

The getErrors solution is not pretty, but it is very simple and one can easily see how it might be improved to provide clearer messages.

The JavaScript:

var app = angular.module('app', ['FormErrors']);
app.controller('MainCtrl', ['$scope', function ($scope) {

    $scope.people = [{name: ''}, {name: ''}];
    $scope.allErrors = [];
    $scope.getErrors = getErrors;

    function getErrors(formObject){
        $scope.allErrors = [];
        extractErrors(formObject)
    }
    function extractErrors(formObject, parent) {
        for (var e in formObject.$error) {
            var path = parent ? parent + "." + e + "." + formObject.$name : formObject.$name + "." + e;
            var err = formObject.$error[e];
            if (err instanceof Array){ // this is an array of sub-forms
                err.forEach(function (subForm, i) {
                    extractErrors(subForm, path + "[" + i + "]");
                });
            } else  {
                if (err === true) {
                    path = path.replace(new RegExp("." + e, "g"), "");
                    $scope.allErrors.push(path + ": " + e);
                }
            }
        }
    }
}]);
like image 27
dave walker Avatar answered Oct 12 '22 09:10

dave walker