Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add validation attributes to md-autocomplete angular material directive

I'm using version 0.7.1 of angular material. I'm using the autocomplete as described here: Autocomplete demo

However, it doesn't seem to support validation logic, even though it generates a textarea: Autocomplete directive documentation

I imagine that I can add logic in the querySearch function to switch ng-valid to ng-invalid. Is this correct? If this is the case, then I need a handle on the md-autocomplete, but this is difficult, because the name attribute gets removed.

like image 416
trees_are_great Avatar asked Mar 25 '15 17:03

trees_are_great


People also ask

How does angular validate autocomplete?

Create custom validator for autocomplete Working with reactive forms, the easiest way to solve this issue is to write a custom form validator. This function evaluates the value of a control and return a validation error if the value is a string type.

What is MD autocomplete?

The md-autocomplete, an Angular Directive, is used as a special input control with an inbuilt dropdown to show all possible matches to a custom query. This control acts as a real-time suggestion box as soon as the user types in the input area.


Video Answer


3 Answers

Quick update, got the solution on Angular Material site (Latest release 1.0.0-), https://material.angularjs.org/latest/demo/autocomplete.

You will find that 'required' and 'ng-messages' are supported now.

<div ng-controller="DemoCtrl as ctrl" layout="column" ng-cloak>
<md-content class="md-padding">
<form ng-submit="$event.preventDefault()" name="searchForm">
  <p>The following example demonstrates floating labels being used as a normal form element.</p>
  <div layout-gt-sm="row">
    <md-input-container flex>
      <label>Name</label>
      <input type="text"/>
    </md-input-container>
    <md-autocomplete flex required
        md-input-name="autocompleteField"
        md-input-minlength="2"
        md-input-maxlength="18"
        md-no-cache="ctrl.noCache"
        md-selected-item="ctrl.selectedItem"
        md-search-text="ctrl.searchText"
        md-items="item in ctrl.querySearch(ctrl.searchText)"
        md-item-text="item.display"
        md-floating-label="Favorite state">
      <md-item-template>
        <span md-highlight-text="ctrl.searchText">{{item.display}}</span>
      </md-item-template>
      <div ng-messages="searchForm.autocompleteField.$error" ng-if="searchForm.autocompleteField.$touched">
        <div ng-message="required">You <b>must</b> have a favorite state.</div>
        <div ng-message="minlength">Your entry is not long enough.</div>
        <div ng-message="maxlength">Your entry is too long.</div>
      </div>
    </md-autocomplete>
  </div>
</form>

like image 121
Henry Neo Avatar answered Oct 18 '22 22:10

Henry Neo


Read documentation

you need these options

md-autocomplete validation

You can use above as below to run yr custom validation :

Update yr template as below

 template:'<span ng-show="validationCheck">yr msg here</span><md-autocomplete\
               md-no-cache="noCache"\
               md-selected-item="selectedItem"\
               md-search-text="searchText"\
               md-items="item in querySearch(searchText)"\
               md-item-text="item.display"\
               placeholder="search query"\
               md-selected-item-change="validate2(searchText)"\
               md-search-text-change="validate(searchText)">\
               <span md-highlight-text="searchText">{{item.display}}</span>\
             </md-autocomplete>'

and add following yr md-auto-complate controller

$scope.validationCheck=false;
  $scope.validate=function(data){
    $scope.validationCheck=true;
    console.log('validation : '+data);
  }
  $scope.validate2=function(data){
    console.log('validation2 :'+data);
  }
like image 1
nitin Avatar answered Oct 18 '22 21:10

nitin


I was working with same approach with the form validation using auto-complete in angular materials.But unfortunately, validation on this directive is not so smooth as input components. So I made up my mind to overcome this issue and did some R&D for this component. Please find below code snippets and they will help you out on this.

HTML:

<div ng-controller="DemoCtrl as ctrl" layout="column" ng-cloak="" class="autocompletedemoBasicUsage" ng-app="MyApp">
<md-content class="md-padding">
<form ng-submit="$event.preventDefault()" name="registerForm" novalidate>
  <p>Use <code>md-autocomplete</code> to search for matches from local or remote data sources.</p>
  <md-autocomplete md-input-name="Country" ng-disabled="ctrl.isDisabled" md-no-cache="ctrl.noCache" md-selected-item="ctrl.selectedItem" md-search-text-change="ctrl.searchTextChange(ctrl.searchText)" md-search-text="ctrl.searchText" md-selected-item-change="ctrl.selectedItemChange(item)" md-items="item in ctrl.querySearch(ctrl.searchText)" md-item-text="item.display" md-min-length="0" placeholder="What is your favorite US state?" ng-class="{'validate': registerForm.Country.$touched && !vm.country1}">
    <md-item-template>
      <span md-highlight-text="ctrl.searchText" md-highlight-flags="^i">{{item}}</span>
    </md-item-template>
    <md-not-found>
      No states matching "{{ctrl.searchText}}" were found.
      <a ng-click="ctrl.newState(ctrl.searchText)">Create a new one!</a>
    </md-not-found>
  </md-autocomplete>

  <div class="ng-message" ng-messages="registerForm.Country.$error" ng-show="registerForm.Country.$touched" role="alert">
    <div class="validate" ng-show="registerForm.Country.$touched && ctrl.country1 == ''" ng-class="{'slide': registerForm.Country.$touched && ctrl.country1 == ''}">
      <span>Country field is required</span>
    </div>
    <div class="validate" ng-show="ctrl.country1 == null" ng-class="{'slide': ctrl.country1 == null}">
      <span>Please enter valid Country</span>
    </div>
  </div>
  <br>
  <md-button class="medium-button success-button" aria-label="submit" ng-disabled="registerForm.$invalid || registerForm.$pristine || !ctrl.country1" ng-click="ctrl.registerUser()">
    Submit
  </md-button>
</form>
</md-content>
</div>

SCRIPT:

(function () {
'use strict';
angular
  .module('MyApp',['ngMaterial', 'ngMessages', 'material.svgAssetsCache'])
  .controller('DemoCtrl', DemoCtrl);

function DemoCtrl ($timeout, $q, $log) {
var self = this;

self.simulateQuery = false;
self.isDisabled    = false;

// list of `state` value/display objects
self.states        = loadAll();
self.querySearch   = querySearch;
self.selectedItemChange = selectedItemChange;
self.searchTextChange   = searchTextChange;

self.newState = newState;

 function newState(state) {
  alert("Sorry! You'll need to create a Constituion for " + state + " first!");
}


function querySearch (query) {
  var results = query ? self.states.filter( createFilterFor(query) ) : self.states,
      deferred;
  if (self.simulateQuery) {
    deferred = $q.defer();
    $timeout(function () { deferred.resolve( results ); }, Math.random() * 1000, false);
    return deferred.promise;
  } else {
    return results;
  }
}

function searchTextChange(text) {
  //$log.info('Text changed to ' + text);
  if(text)
    self.country1 = text.match(/^[a-zA-Z0-9\_\- ]*$/);
  else
    self.country1 = '';

  if (text)
    self.country = text;

  $log.info('Item changed to ' + self.country1);
}

function selectedItemChange(item) {
  if(item)
    self.country1 = item.match(/^[a-zA-Z0-9\_\- ]*$/);
  else
    self.country1 = '';

  if (item)
    self.country = item;

  $log.info('Item changed to ' + self.country1);
}

/**
 * Build `states` list of key/value pairs
 */
function loadAll() {
  var allStates = 'Alabama, Alaska, Arizona, Arkansas, California, Colorado, Connecticut, Delaware,\
          Florida, Georgia, Hawaii, Idaho, Illinois, Indiana, Iowa, Kansas, Kentucky, Louisiana,\
          Maine, Maryland, Massachusetts, Michigan, Minnesota, Mississippi, Missouri, Montana,\
          Nebraska, Nevada, New Hampshire, New Jersey, New Mexico, New York, North Carolina,\
          North Dakota, Ohio, Oklahoma, Oregon, Pennsylvania, Rhode Island, South Carolina,\
          South Dakota, Tennessee, Texas, Utah, Vermont, Virginia, Washington, West Virginia,\
          Wisconsin, Wyoming';

  return allStates.split(/, +/g).map( function (state) {
    return state;
  });
}

/**
 * Create filter function for a query string
 */
function createFilterFor(query) {
  var lowercaseQuery = angular.lowercase(query);

  return function filterFn(state) {
    return (state.value.indexOf(lowercaseQuery) === 0);
  };

  }
 }
})();

See the full example of codepen here

like image 1
Krunal Avatar answered Oct 18 '22 20:10

Krunal