如何将验证属性添加到 md-autocomplete angular material 指令

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

我使用的是 angular material 的 0.7.1 版。我正在使用此处描述的自动完成功能: Autocomplete demo

然而,它似乎不支持验证逻辑,即使它生成了一个文本区域: Autocomplete directive documentation

我想我可以在querySearch 函数中添加逻辑以将ng-valid 切换为ng-invalid。这个对吗?如果是这种情况,那么我需要 md-autocomplete 的句柄,但这很困难,因为名称属性被删除了。

Read documentation

你需要这些选项

您可以使用上面的方法 运行 年自定义验证:

更新年模板如下

 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>'

并添加以下 yr md-auto-complate 控制器

$scope.validationCheck=false;
  $scope.validate=function(data){
    $scope.validationCheck=true;
    console.log('validation : '+data);
  }
  $scope.validate2=function(data){
    console.log('validation2 :'+data);
  }

看来我不是唯一一个觉得这很棘手的人。很快就会有一个解决方案: Autocomplete validation improvements in progress

快速更新,在 Angular Material 网站上找到了解决方案(最新版本 1.0.0-), https://material.angularjs.org/latest/demo/autocomplete.

您会发现现在支持 'required' 和 'ng-messages'。

<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>

我在 angular materials.But 中使用自动完成的表单验证使用相同的方法,不幸的是,对该指令的验证不如输入组件那么顺利。所以我下定决心要克服这个问题,并对该组件进行了一些研发。请在下面找到代码片段,它们将帮助您解决这个问题。

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>

脚本:

(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);
  };

  }
 }
})();

查看 codepen 的完整示例 here