Tips on incorporating validations such as require and pristine into custom Angular directives

I have recently developed an angular directive that allows users to choose multiple contact types from a modal dialog within an ionic app.

angular.module('SharedModule')
    .directive('multiSelect', ['$ionicModal', multiSelect]);


function multiSelect($ionicModal) {
    return {
        restrict: 'E',
        template: [
            '<div ng-click="showItems($event)" class="item-icon-right item">',
            '{{text}}',
            '<i class="icon ion-ios-arrow-right"></i>',
            '</div>'
        ].join(""),
        scope: {
            'items': '=',
            'value': '=ngModel'
        },
        link: function (scope, element, attrs, $filter) {
            //validations
            //if (typeof attrs.required != "undefined"){
            //    // a value is required, hence invalidate this control.
            //
            //}

            //Some specific logic here. 

            scope.validate = function () {
                // validation that kicks in when user chooses to close the modal. 
            };

            scope.$on('$destroy', function () {
                scope.modal.remove();
            });
        }
    }
}

When using this directive in my HTML form, it looks like this:

<multi-select
    name="contactTypes"
    items="contact_types"
    text="Contact types"
    header-text="Choose contact types"
    allow-empty="false"
    ng-model="contact.contact_types"
    ></multi-select>

Query: I am uncertain about how to handle the setting of ng-pristine, ng-required, and ng-untouched classes if a user has not selected anything. Where should I place the custom validation code? What steps do I need to take in order to use this directive just like any other input control with ng-model?

Answer №1

If you want to make use of ng-model, you can refer to the information provided here (specifically under "Custom Control Example"). Here is a brief summary:

  1. To start, ensure you require the ngModel:

    function multiSelect($ionicModal) {
        return {
            ...
            require: 'ngModel',
            ...
        };
    }
    
  2. In the link function, obtain the ngModel and redefine the $isEmpty function. The default checks if the value is undefined, '', null, or NaN. You may want to include an empty array in this check, for example:

    link: function(scope, element, attrs, ngModel) {
        ...
        var originalIsEmpty = ngModel.$isEmpty;
    
        ngModel.$isEmpty = function(value) {
            return originalIsEmpty.call(ngModel, value) || value.length === 0;
        };
        ...
    }
    
  3. After completing the above steps, simply add ng-required to your directive:

    <multi-select ... ng-required="true"></multi-select>
    

    Angular will utilize your customized $isEmpty method and attach the ng-invalid-required class to the <multi-select> element.

The functionality of $pristine and $untouched should ideally work as expected. If not, you might need to manually call the relevant methods of ngModel:

  1. When the user opens the dialog - marking the control as touched, execute ngModel.$setTouched().
  2. Upon the user clicking "OK" in the dialog box AND making actual changes - signifying that the control value has been altered and is no longer pristine, run ngModel.$setDirty().

By having access to ngModel in the link function, the inclusion of scope: { 'value': '=ngModel' } becomes unnecessary.

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

The feature to navigate to a different section on another page is experiencing a malfunction

I'm facing an issue with my navbar setup: <ul class="dropdown-menu" role="menu"> <li><a href="/main_page#top_something">People</a></li> <li><a href="/main_page"&g ...

JavaScript - store disassembled objects in a fresh variable

I'm working on implementing Destructing on a variable, inspired by the example found in MDN: var people = [ { name: 'Mike Smith', family: { mother: 'Jane Smith', father: 'Harr ...

Retrieve information from a JSON API on one server and showcase it on an HTML page hosted on a different server

I have a situation where I need to transfer data from one project (Project1) to another project (Project2). To achieve this, I decided to convert the Project1 data stored in a database into a JSON API and then call it using an HTML page from Project2. Howe ...

Issue with idangero.us swiper: resizing problem occurs when image exceeds window size

Having an issue where resizing my window causes the image to become larger than anticipated. As a result, the current image is partially cropped on the left side while the previous image starts to show through. Here's a description of what's happ ...

Implementing dynamic https URL embedding in AngularJS based on the user's browser location

When my webpage built with angularjs is launched using https, all urls within the page should also use https instead of the default http. Is it possible to make angularjs use either http or https based on the initial request? Here are some example embedd ...

Recursive array filtering

My goal is to recursively filter my table using the key "excludeInMenu". I have successfully filtered the first table but am struggling with filtering the second content within "Items". Here is the code snippet I am currently using: {routes.filter(route = ...

What impact does async await have on the asynchronous nature of JavaScript?

Although JavaScript is synchronous, we utilize callback promises and async-await to achieve asynchronous behavior. However, with async-await, the code waits for the await statement to be completed before proceeding to the next statement, which may seem s ...

evaluation is not being executed in javascript

I am struggling to assign a value of 1 to the educationflag variable. I am trying to avoid calling the enableEdit.php file when the flag is set to 1. The issue arises when control reaches the if condition but fails to set the variable to 1. Here is my cod ...

Data will not bind with Laravel and Vue

I am currently working on a Laravel project and trying to develop a basic editing feature for posts. My approach involves using Vue.js 2 to bind the data, but unfortunately, I am facing issues with displaying it - I'm not quite sure what's causin ...

Using feature flags in Vue for enhanced functionality

I am interested in incorporating a "feature toggling mechanism" into my Vue application. Although I have set up a basic system, I want to explore the methods outlined in a article by Pete Hodgson. The concept of "Inversion of Decision" seems particularly i ...

Connecting a Kendo Dropdown menu to external data sources for seamless integration

I need help with binding data to a dropdown list for my local service. Whenever I try to download the data, I keep getting an error message: Uncaught SyntaxError: Unexpected token: Does anyone have any ideas on how to resolve this issue? This is my JS ...

Encountering issues while trying to duplicate react-table CodeSandbox: API error when using localhost

Trying to implement this CodeSandbox project into my own project has been challenging. On navigating to the Example component, a 404 error pops up: Error: Request failed with status code 404. The API is targeting this endpoint: http://localhost:3000/api/pr ...

How to dynamically add list items to a jQuery Mobile list using Ajax requests

Included in my index.html is a list view: <section id="dashboard" data-role="page" data-transition="slide"> <header data-role="header"> <h1>Trips</h1> <a href="#addTrip" id="createNewTrip" d ...

Utilizing FlatList in React Native to display a parsed JSON array response

Can anyone help me with parsing the JSON response below into a FlatList? I'm not sure what I'm missing since it doesn't follow the standard key and value pair structure for rendering. {"list":["a","b","c","d"]} Here is my code... impo ...

What is the best way to extract specific values from these JSON objects?

I'm struggling with extracting the "name" values from JSON code returned by an online API. Despite trying various approaches, such as .people.name, I keep getting either a blank output or "[object Object][object Object][object Object][object Object][o ...

Leveraging the power of jQuery to capture and recycle a dynamically generated date

Using a jQuery plugin, a list of dates is generated. Implementing moment.js works perfectly fine as shown in this fiddle (http://jsfiddle.net/UJ9z4/). However, when attempting to apply it to the live file with the plugin running, an undefined error is enc ...

Ways to initiate a page redirection within the componentWillReceiveProps lifecycle method

When my webpage or component generates a form and sends it to the backend API upon submission, I receive an object in return if the process is successful. This object is then added to my redux store. In order to determine whether the reducer successfully ...

the useRef utility function with 'smooth' behavior

I'm currently working on a helper function for my React application, but I've run into an issue where the 'smooth' behavior is not functioning as expected. const scrollRef = useRef() const handleScroll = (ref) => { return ref.cu ...

Facebook pages and tabs utilize the [fbjs] JavaScript library

I am struggling to implement tabbing functionality on a Facebook application (business) tabs. Despite having some basic HTML and JS [fbjs], the code I have doesn't seem to be working. I can't figure out what is wrong. <div id="foo">foo di ...

Issue with AngularJS: Service causing two-way binding failure

I'm currently diving into Angular with the help of W3Schools. I recently made changes to a sample related to "Services"... Here's the updated code: <!DOCTYPE html> <html> <script src="http://ajax.googleapis.com/ajax/libs/angula ...