Angular Material 输入验证错误消息全部显示在彼此之上

Angular Material input validation error messages all showing on top of eachother

我正在 angular material 中创建一个网站,除了对表单输入的验证外,它运行良好。

当我在输入框中键入内容时,所有错误消息(必填、最小长度和最大长度)都显示在彼此顶部的同一位置。

这是 angular material 中的错误还是我做错了什么?

这是我的问题的简化版本,仅使用默认的 StarterApp 示例,在主页内容中输入表单。如果您 运行 它并在文本框中键入内容,您应该会看到问题所在。谢谢你的帮助。

<html lang="en" ng-app="StarterApp">

<head>
  <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/angular_material/0.11.0/angular-material.min.css">
  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=RobotoDraft:300,400,500,700,400italic">
  <meta name="viewport" content="initial-scale=1" />
</head>

<body layout="column" ng-controller="AppCtrl">
  <md-toolbar layout="row">
    <div class="md-toolbar-tools">
      <md-button ng-click="toggleSidenav('left')" hide-gt-sm class="md-icon-button">
        <md-icon aria-label="Menu" md-svg-icon="https://s3-us-west-2.amazonaws.com/s.cdpn.io/68133/menu.svg"></md-icon>
      </md-button>
      <h1>Hello World</h1>
    </div>
  </md-toolbar>
  <div layout="row" flex>
    <md-sidenav layout="column" class="md-sidenav-left md-whiteframe-z2" md-component-id="left" md-is-locked-open="$mdMedia('gt-sm')">

    </md-sidenav>
    <div layout="column" flex id="content">
      <md-content layout="column" flex class="md-padding">
        <form name="userForm">
          <md-input-container>
            <label>Username</label>
            <input name="username" ng-model="data.username" required md-maxlength="20" minlength="3">
            <div ng-messages="userForm.username.$error" ng-show="userForm.username.$dirty">
              <div ng-message="required">This field is required</div>
              <div ng-message="md-maxlength">Your username can not be longer than 20 characters</div>
              <div ng-message="minlength">Your username can not be shorter than 3 characters</div>
            </div>
          </md-input-container>
          {{data.username}}
        </form>
      </md-content>
    </div>
  </div>
  <!-- Angular Material Dependencies -->
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-animate.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-aria.min.js"></script>

  <script src="https://ajax.googleapis.com/ajax/libs/angular_material/0.11.0/angular-material.min.js"></script>

  <!-- custom stuff -->
  <style>
    .md-toolbar-tools h1 {
      font-size: inherit;
      font-weight: inherit;
      margin: inherit;
    }
  </style>
  <script>
    var app = angular.module('StarterApp', ['ngMaterial']);

    app.controller('AppCtrl', ['$scope', '$mdSidenav',
      function($scope, $mdSidenav) {
        $scope.data = {
          username: ""
        };
        $scope.toggleSidenav = function(menuId) {
          $mdSidenav(menuId).toggle();
        };

      }
    ]);
  </script>
</body>

</html>

问题出在 angular-material.min.css 文件上。 md-input-container 在该文件中的位置是绝对的。添加您自己的 css 并将位置设置为相对而不是绝对。为这些 div 添加了内联样式,这样你就可以看到

<html lang="en" ng-app="StarterApp">

<head>
  <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/angular_material/0.11.0/angular-material.min.css">
  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=RobotoDraft:300,400,500,700,400italic">
  <meta name="viewport" content="initial-scale=1" />
</head>

<body layout="column" ng-controller="AppCtrl">
  <md-toolbar layout="row">
    <div class="md-toolbar-tools">
      <md-button ng-click="toggleSidenav('left')" hide-gt-sm class="md-icon-button">
        <md-icon aria-label="Menu" md-svg-icon="https://s3-us-west-2.amazonaws.com/s.cdpn.io/68133/menu.svg"></md-icon>
      </md-button>
      <h1>Hello World</h1>
    </div>
  </md-toolbar>
  <div layout="row" flex>
    <md-sidenav layout="column" class="md-sidenav-left md-whiteframe-z2" md-component-id="left" md-is-locked-open="$mdMedia('gt-sm')">

    </md-sidenav>
    <div layout="column" flex id="content">
      <md-content layout="column" flex class="md-padding">
        <form name="userForm">
          <md-input-container>
            <label>Username</label>
            <input name="username" ng-model="data.username" required md-maxlength="20" minlength="3">
            <div style="position: relative" ng-messages="userForm.username.$error" ng-show="userForm.username.$dirty">
              <div style="position: relative" ng-message="required">This field is required</div>
              <div style="position: relative" ng-message="md-maxlength">Your username can not be longer than 20 characters</div>
              <div style="position: relative" ng-message="minlength">Your username can not be shorter than 3 characters</div>
            </div>
          </md-input-container>
          {{data.username}}
        </form>
      </md-content>
    </div>
  </div>
  <!-- Angular Material Dependencies -->
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-animate.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-aria.min.js"></script>

  <script src="https://ajax.googleapis.com/ajax/libs/angular_material/0.11.0/angular-material.min.js"></script>

  <!-- custom stuff -->
  <style>
    .md-toolbar-tools h1 {
      font-size: inherit;
      font-weight: inherit;
      margin: inherit;
    };
    .md-input-container-absolute {
     position: relative;
    }

  </style>
  <script>
    var app = angular.module('StarterApp', ['ngMaterial']);

    app.controller('AppCtrl', ['$scope', '$mdSidenav',
      function($scope, $mdSidenav) {
        $scope.data = {
          username: ""
        };
        $scope.toggleSidenav = function(menuId) {
          $mdSidenav(menuId).toggle();
        };

      }
    ]);
  </script>
</body>

</html>