Reputation: 672
I'm making a website in angular material, which is working great except for the validation on form inputs.
When I type something into the input box, all of the error messages (required, minlength and maxlength) are show in the same place on top of each other.
Is this a bug in angular material or is there something I'm doing wrong?
This a simplified version of my problem just using the default StarterApp example, with the form input in the main page content. If you run it and type something in the text box, you should see the problem. Thank you for helping.
<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>
Upvotes: 0
Views: 3800
Reputation: 1269
The problem is with the angular-material.min.css file. Position in that file for md-input-container is absolute. Add your own css and set the position to relative instead of absolute. Added inline style to those divs so you could see
<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>
Upvotes: 1