Learn how to program AngularJS to automatically set all inputs as $touched without the need for a submit

In my project, I have implemented a directive that performs input validation within a form based on the values of their properties such as $valid and $untouched. The directive checks for validation when the input is "touched" and changes the font and border colors to red or green accordingly. However, if the input remains "untouched", no action is taken.

Due to using ngBootBox's custom dialog, I do not have a submit type button in my form. Instead, I rely on the callback function of the "Create" button to handle data passing and saving.

An issue arises when I click the "create" button and some fields are left empty, causing the form to be considered invalid. Since the inputs remain untouched, the $watch function does not get triggered. Is there a way to force all child inputs of the form to be marked as touched with something like $scope.createProjectForm.$setTouched(true)?

I attempted another approach by iterating through the inputs and setting them as touched, but it did not yield the desired result:

angular.forEach($scope.createProjectForm, function(field){
   field.$setTouched(true);
});

Below is the code for my validation directive:

angular.module('mean.theme').directive("inputValidation", function () {
    return {
        restrict: 'EA',
        require: 'ngModel',
        link: function (scope, inputElement, attrs, ngModelCtrl) {
            // Validation logic here
        }
    };
});

This snippet shows part of my controller code where the create function is defined:

$scope.create = function () {
    // Dialog options and logic here
};

Lastly, this portion presents the structure of my form in HTML:

<form role="form" name="createProjectForm">
    <!-- Form inputs here -->
</form>
  • EDIT:

After further exploration, I discovered a simpler method to achieve the desired behavior:

You can manually set:

$scope.createProjectForm.$setSubmitted()
to true

Then, you can implement a $watch function on the children (inputs) to monitor this change:

scope.$watchGroup([
            function(){
                return ngModelCtrl.$untouched;
            },
            function(){
                return ngModelCtrl.$valid;
            },
            function(){
                return ngModelCtrl.$$parentForm.$submitted;
            }
        ], function(Paramaters){
         // Code implementation here
        }

Answer №1

To implement this functionality, consider structuring your code in the following way:

if ($scope.form.$invalid) {
    angular.forEach($scope.form.$error, function (field) {
        angular.forEach(field, function(errorField){
            errorField.$setTouched();
        });
    });
}

For more information on '$setTouched', visit: https://docs.angularjs.org/api/ng/type/ngModel.NgModelController

Answer №2

When dealing with nested forms:

function setFormTouched(form) {
        // Check if the form/property has the $setSubmitted method
        if (form.hasOwnProperty('$submitted')) {
            // Loop through each of the required error properties
            angular.forEach(form.$error, function (errorType) {
                // Loop through each error type
                angular.forEach(errorType, function (prop) {
                    // Confirm that the property has the $setTouched method
                    if (prop.hasOwnProperty('$touched')) prop.$setTouched();
                    // Recursively handle nested forms
                    setFormTouched(prop);
                });

            });
        }
    }

This solution was inspired by Patrick Marabeas' codepen, but modifications were made to address issues with the hasOwnProperty function not working as expected for functions defined in prototype.

if(prop.hasOwnProperty('$setTouched'))

consistently returned false in my case.

UPDATE: Initially, I needed a better way for users to detect errors within nested tabs. The final scope function utilized for enabling/disabling submit button and displaying error messages is shown below:

$scope.isFormValid = function (topLevelForm) {
        if (topLevelForm.$valid) {
            return true;
        }

        // Form invalid, trigger fields for easier error identification
        setFormTouched(topLevelForm);

        function setFormTouched(form) {
            // Check if the form/property has the $setSubmitted method
            if (form.hasOwnProperty('$submitted')) {
                // Loop through each of the required error properties
                angular.forEach(form.$error, function (errorType) {
                    // Loop through each error type
                    angular.forEach(errorType, function (prop) {
                        // Confirm that the property has the $setTouched method
                        if (prop.hasOwnProperty('$touched')) prop.$setTouched();
                        // Recursive call to manage nested forms
                        setFormTouched(prop);
                    });

                });
            }
        }
        return false;
    };

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Experience the innovative feature of React Splide Carousel where a peek of the next image is shown until you reach

My current challenge arises when I reach the last slide in the slider. I am trying to prevent it from looping and instead stop with no extra space or any other images peeking out. To address this, I have utilized the padding: '5%' option, which ...

Jquery syntax for working with objects in Javascript

I am currently working on implementing a jQuery right mouse menu on my page, but I'm facing challenges in structuring it correctly for easy population. On my page, there is a list of items (an HTML table) that users can review. Depending on the user& ...

Unusual clash between ngAnimate and ngRoute

There seems to be an unusual issue occurring between ngAnimate and ngRoute that I have noticed. Whenever I attempt to reload the current route without refreshing the entire page, something goes awry and my leaflet map fails to reinitialize. To illustrate t ...

Using JavaScript, extract individual objects from a JSON object

Recently, I've been tasked with displaying items from a JSON-file in a well-organized manner. However, the format of the JSON file is unfamiliar to me. The code snippet provided below pertains to this task: function readFile(file) { var rawFile = ...

The behavior of Quasar's q-drawer is quite unpredictable

Having made the transition from Vue.js 2 with Vuetify to Vue.js 3 with Quasar due to Vuetify not officially supporting Vue.js 3 yet, I am utilizing q-drawer and its mini property. This allows me to toggle between the mini state and the normal expanded stat ...

Incorporating Jest to fake the Express Response.setHeader method: A guide

I developed a unique Express middleware that validates if the request content type is JSON. If it's not, the server will return a 415 error along with a custom error object. import { Request, Response, NextFunction } from "express"; functio ...

Is React dependent on the render process to update its state?

In my code, I am encountering an issue where the state of a key is not updating correctly even after performing operations on its value within a function. The scenario involves a function named clickMe, which is triggered by an onClick event for a button ...

"Div does not perfectly match the height of its parent div when using the 'inherit' value

I have 3 divs inside a parent div, intended to be arranged like so: ______________________________________ | | | HEADER | |______________________________________| ____ ________________ ...

How can I extract an array of objects from an array of arrays containing objects?

Here is the array I am currently working with: let findAllSegmentProjectMediaFilesXref = [ { it: 0, bt: 0, items: [ { mute: false, startPosition: 10, endPosition: 20, ...

The primeVue menubar's active/focused item highlighting feature is not functioning correctly

Currently, we are in the process of developing an electron-based application with the front end primarily coded using Vue.js and primeVue. As a novice, I am encountering issues with the menubar component from primeVue. The problem is that no matter which i ...

The JSX element 'body' appears to be missing its closing tag

I'm currently in the process of developing a landing page using react.js. This particular page is designed for users who are not yet signed up to create an account if they wish to do so. Unfortunately, I'm encountering some errors, one of which p ...

Taking out the hashtag from AngularJS integration with SailsJS

I'm feeling really frustrated about setting up the Routing on our app, which uses sailsJS and angularJS. The issue is that the browser doesn't recognize angular, so any request like /login results in a 404 Error from sails. I need to find a way ...

Customize Column Headers in Handsontable: A Quick Guide

Is there a way to customize the appearance of column headers in handsontable? I have provided a jsfiddle example to showcase my current progress. While I am able to format the first row of data and change the column titles, I am facing difficulty in forma ...

Creating a lateral navigation bar in Angular Material

Hey there! I'm new to Angular Material and was wondering if anyone could assist me in adding a horizontal navigation bar for my project. I've been having trouble finding one that fits my needs. Thank you in advance for your help! Keep up the grea ...

What are the steps to generate a service instance?

I am working on a unique service: (angular .module('app.services', ['ngResource']) .factory('MyService', [ /******/ '$resource', function ($resource) { return $resource('myurl'); ...

"Unexpected discrepancy: Bootstrap Glyphicon fails to appear on webpage, however, is visible

I am having some trouble getting the glyphicon to display properly in my side nav. The arrow head should rotate down, which is a pretty standard feature. Here is the link to the page: The glyphicon should be visible on the "Nicky's Folders" top leve ...

"Emphasizing the Html.ActionLink menu for improved user navigation and

Currently, I am facing an issue with my menu. I want to clear previously visited links while keeping the current one styled as a:visited in CSS. Although I have attempted to achieve this, unfortunately, the code is not functioning properly. Here is what I ...

The problem with the Image Gallery carousel not functioning properly in a right-to-left direction arises when attempting to modify

I have been developing an image gallery that functions perfectly in the English version of the website. Now, I am tasked with replicating the same functionality for another version of the website that requires right-to-left (RTL) direction. However, when I ...

How can I ensure an element fills the width of its container without being pushed out by margins?

Is there a way to make an element adjust its width based on the container size without overflowing it? body { -moz-osx-font-smoothing: grayscale; font-family:Verdana; font-weight:normal; font-size:12px; } #BorderContainer2085 { position:absolute; top: ...

Every piece of data entered in Next.js triggers a complete refresh

Currently, I am developing a Next.js application using version 12.1.5. However, I have encountered a perplexing bug. Every input component triggers a full re-render with each keystroke, causing the input to lose focus. This issue persists across various co ...