How to add validation attributes to md-autocomplet

2019-06-17 01:23发布

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.

4条回答
Deceive 欺骗
2楼-- · 2019-06-17 01:37

It seems that I am not the only one to find this tricky. There will be a solution to this soon: Autocomplete validation improvements in progress

查看更多
够拽才男人
3楼-- · 2019-06-17 01:54

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>

查看更多
【Aperson】
4楼-- · 2019-06-17 02:00

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

查看更多
虎瘦雄心在
5楼-- · 2019-06-17 02:03

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);
  }
查看更多
登录 后发表回答