自定义 DatePicker Angular Formly 字段不会出现验证错误消息
Validation error message doesn't appear for custom DatePicker Angular Formly field
我正在尝试使用 Angular Datetime Picker as a Angular Formly 输入类型。我让它正常工作,这样我就可以编辑和设置一个正确添加到绑定模型的值。
但是,我无法像常规输入字段那样显示验证错误消息。
JS Bin with what I've got so far。如您所见,当您退出该字段时红色不会出现,只有当您尝试提交时才会出现。而且错误消息永远不会出现。
正式配置:
formlyConfigProvider.setType({
name: 'datepicker',
templateUrl: "custom-template.html",
overwriteOk: true,
wrapper: ['bootstrapHasError'],
defaultOptions: function defaultOptions(options) {
return {
templateOptions: {
validation: {
show: true
}
}
};
}
});
formlyConfigProvider.setWrapper({
name: 'validation',
types: ['input', 'datepicker'],
templateUrl: 'error-messages.html'
});
字段
vm.fields = [
{
key: 'text',
type: 'input',
templateOptions: {
label: 'Text',
placeholder: 'Write something',
required: true
},
},
{
key: 'date',
type: 'datepicker',
templateOptions: {
label: 'Date',
placeholder: 'Pick a date',
required: true
},
}
];
模板
<script type="text/ng-template" id="custom-template.html">
<div class="form-group">
<label class="control-label" for="{{::id}}">{{to.label}} {{to.required ? '*' : ''}}</label>
<div class="dropdown">
<a class="dropdown-toggle" id="dropdown-{{options.key}}" role="button" data-toggle="dropdown">
<div class="input-group">
<input id="{{::id}}" name="{{::id}}" type="text" data-date-time-input="YYYY-MM-DD" class="form-control" data-ng-model="model[options.key]"><span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span>
</div>
</a>
<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
<datetimepicker
data-ng-model="model[options.key]"
data-datetimepicker-config="{ dropdownSelector: '#dropdown-' + options.key, minView: 'day', startView: 'year', modelType: 'YYYY-MM-DDTHH:mm:ssZ'}"/>
</ul>
</div>
</div>
</script>
<script type="text/ng-template" id="error-messages.html">
<formly-transclude></formly-transclude>
<div ng-messages="fc.$error" ng-if="form.$submitted || options.formControl.$touched" class="error-messages">
<div ng-message="{{ ::name }}" ng-repeat="(name, message) in ::options.validation.messages" class="message">{{ message(fc.$viewValue, fc.$modelValue, this)}}</div>
</div>
</script>
您应该在 formlyConfigProvider
中 return
您的 validation
而不是将其作为 templateOptions
的值传递。 Return
validation: {
show: true
}
而不是
templateOptions: {
validation: {
show: true
}
}
您的 formlyConfigProvider
应如下所示:
formlyConfigProvider.setType({
name: 'datepicker',
templateUrl: "custom-template.html",
overwriteOk: true,
wrapper: ['bootstrapHasError'],
defaultOptions: function defaultOptions(options) {
return {
validation: {
show: true
}
};
}
});
Here 是工作代码的 JSBin。
深入调查后,我可以看到您使用的控件 Angular Datetime Picker is not fully compatible with Angular Formly。
This is because of the reason that it's overwriting the AngularJS's
ngModelController.$render()
method and hence not setting the value
for $touched
like other input controls.
Another reason in your code is, the config and the template
error-messages.html
are treating the custom control as single
element with fc.$touched
, fc.$error
and fc.$viewValue
whereas
DatePicker
is rendering as group of elements (array).
要摆脱所有这些问题,您可以使用自定义指令来设置 $touched
,如下所示,
app.directive('setTouched', function MainCtrl() {
return {
restrict: 'A', // only activate on element attribute
require: '?ngModel', // get a hold of NgModelController
link: function(scope, element, attrs, ngModel) {
if (!ngModel) return; // do nothing if no ng-model
element.on('blur', function() {
var modelControllers = scope.$eval(attrs.setTouched);
if(angular.isArray(modelControllers)) {
angular.forEach(modelControllers, function(modelCntrl) {
modelCntrl.$setTouched();
});
}
});
}
};
});
并且在 custom-template.html
,
<div class="input-group">
<input set-touched="options.formControl" id="{{::id}}" name="{{::id}}" type="text" data-date-time-input="YYYY-MM-DD" class="form-control" data-ng-model="model['date1']"><span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span>
</div>
并在下面的配置中添加 fc[0].$touched
以处理字段数组,
app.run(function run(formlyConfig, formlyValidationMessages) {
formlyConfig.extras.errorExistsAndShouldBeVisibleExpression = 'form.$submitted || fc.$touched || fc[0].$touched';
formlyValidationMessages.addStringMessage('required', 'This field is required');
});
并在 error-messages.html
中添加以下部分以处理字段数组,
<div ng-messages="fc[0].$error" ng-if="form.$submitted || options.formControl[0].$touched" class="error-messages">
<div ng-message="{{ ::name }}" ng-repeat="(name, message) in ::options.validation.messages" class="message">{{ message(fc[0].$viewValue, fc[0].$modelValue, this)}}</div>
</div>
此更改将解决此问题。
正如您在下方显示的错误消息中看到的一些设计问题,
您可以通过删除 div 包装器 <div class="form-group">
、
来更改 custom-template.html
,如下所示
<script type="text/ng-template" id="custom-template.html">
<label class="control-label" for="{{::id}}"
uib-popover="{{options.templateOptions.desc}}"
popover-trigger="mouseenter"
popover-placement="top-left"
popover-popup-delay="500"
popover-append-to-body="true">{{to.label}} {{to.required ? '*' : ''}}</label>
<div class="dropdown">
<a class="dropdown-toggle" id="dropdown-{{options.key}}" role="button" data-toggle="dropdown">
<div class="input-group">
<input set-touched="options.formControl" id="{{::id}}" name="{{::id}}" type="text" data-date-time-input="YYYY-MM-DD" class="form-control" data-ng-model="model['date1']"><span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span>
</div>
</a>
<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
<datetimepicker
data-ng-model="model[options.key]"
data-datetimepicker-config="{ dropdownSelector: '#dropdown-' + options.key, minView: 'day', startView: 'year', modelType: 'YYYY-MM-DDTHH:mm:ssZ'}"/>
</ul>
</div>
</script>
我已经用这些更改更新了您的 JSBin。
片段:
/* global angular */
(function() {
'use strict';
var app = angular.module('formlyExample', ['formly', 'formlyBootstrap', 'ngAnimate', 'ngMessages', 'ui.bootstrap.datetimepicker', 'ui.dateTimeInput'], function config(formlyConfigProvider) {
formlyConfigProvider.setType({
name: 'datepicker',
templateUrl: "custom-template.html",
overwriteOk: true,
wrapper: ['bootstrapHasError'],
defaultOptions: function defaultOptions(options) {
return {
templateOptions: {
validation: {
show: true
}
}
};
}
});
formlyConfigProvider.setWrapper({
name: 'validation',
types: ['input', 'datepicker'],
templateUrl: 'error-messages.html'
});
});
app.run(function run(formlyConfig, formlyValidationMessages) {
formlyConfig.extras.errorExistsAndShouldBeVisibleExpression = 'form.$submitted || fc.$touched || fc[0].$touched';
formlyValidationMessages.addStringMessage('required', 'This field is required');
});
app.directive('setTouched', function MainCtrl() {
return {
restrict: 'A', // only activate on element attribute
require: '?ngModel', // get a hold of NgModelController
link: function(scope, element, attrs, ngModel) {
if (!ngModel) return; // do nothing if no ng-model
element.on('blur', function() {
var modelControllers = scope.$eval(attrs.setTouched);
if(angular.isArray(modelControllers)) {
angular.forEach(modelControllers, function(modelCntrl) {
modelCntrl.$setTouched();
});
}
});
}
};
});
app.controller('MainCtrl', function MainCtrl(formlyVersion) {
var vm = this;
vm.onSubmit = onSubmit;
vm.model = {};
vm.options = {};
vm.env = {
angularVersion: angular.version.full,
formlyVersion: formlyVersion
};
vm.fields = [
{
key: 'text',
type: 'input',
templateOptions: {
label: 'Text',
placeholder: 'Write something',
required: true
},
},
{
key: 'moretext',
type: 'input',
templateOptions: {
label: 'More Text',
placeholder: 'Write something else',
},
},
{
key: 'date',
type: 'datepicker',
templateOptions: {
label: 'Date',
placeholder: 'Pick a date',
required: true
},
}
];
vm.originalFields = angular.copy(vm.fields);
// function definition
function onSubmit() {
if (vm.form.$valid) {
vm.options.updateInitialValue();
alert(JSON.stringify(vm.model), null, 2);
}
}
});
})();
body {
margin: 20px
}
.formly-field {
margin-bottom: 30px;
}
.error-messages {
position: relative;
}
.error-messages, .message {
opacity: 1;
transition: .3s linear all;
}
.message {
font-size: .8em;
position: absolute;
width: 100%;
color: #a94442;
margin-top: 4px;
}
.error-messages.ng-enter.ng-enter-active,
.message.ng-enter.ng-enter-active {
opacity: 1;
top: 0;
}
.error-messages.ng-enter,
.message.ng-enter {
opacity: 0;
top: -10px;
}
.error-messages.ng-leave,
.message.ng-leave {
opacity: 1;
top: 0;
}
.error-messages.ng-leave-active,
.message.ng-leave-active {
opacity: 0;
top: -10px;
}
<!DOCTYPE html>
<html>
<head>
<!-- jQuery -->
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<!-- Twitter bootstrap -->
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.css" rel="stylesheet">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<!-- apiCheck is used by formly to validate its api -->
<script src="//npmcdn.com/api-check@latest/dist/api-check.js"></script>
<!-- This is the latest version of angular (at the time this template was created) -->
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.js"></script>
<!-- This is the latest version of formly core. -->
<script src="//npmcdn.com/angular-formly@latest/dist/formly.js"></script>
<!-- This is the latest version of formly bootstrap templates -->
<script src="//npmcdn.com/angular-formly-templates-bootstrap@latest/dist/angular-formly-templates-bootstrap.js"></script>
<script src="https://rawgit.com/angular/bower-angular-messages/v1.4.4/angular-messages.js"></script>
<script src="https://rawgit.com/angular/bower-angular-animate/v1.4.4/angular-animate.js"></script>
<!-- Moment -->
<script src="https://cdn.rawgit.com/moment/moment/develop/min/moment-with-locales.min.js"></script>
<!-- Datetime picker -->
<script type="text/javascript" src="https://cdn.rawgit.com/dalelotts/angular-bootstrap-datetimepicker/master/src/js/datetimepicker.js"></script>
<script type="text/javascript" src="https://cdn.rawgit.com/dalelotts/angular-bootstrap-datetimepicker/master/src/js/datetimepicker.templates.js"></script>
<link href="https://cdn.rawgit.com/dalelotts/angular-bootstrap-datetimepicker/master/src/css/datetimepicker.css" rel="stylesheet">
<script type="text/javascript" src="https://cdn.rawgit.com/dalelotts/angular-date-time-input/master/src/dateTimeInput.js"></script>
<title>Angular Formly Example</title>
</head>
<body ng-app="formlyExample" ng-controller="MainCtrl as vm">
<div>
<form ng-submit="vm.onSubmit()" name="vm.form" novalidate>
<formly-form model="vm.model" fields="vm.fields" options="vm.options" form="vm.form">
<button type="submit" class="btn btn-primary submit-button">Submit</button>
<button type="button" class="btn btn-default" ng-click="vm.options.resetModel()">Reset</button>
</formly-form>
</form>
<hr />
<h2>Model</h2>
<pre>{{vm.model | json}}</pre>
<h2>Fields <small>(note, functions are not shown)</small></h2>
<pre>{{vm.originalFields | json}}</pre>
<h2>Form</h2>
<pre>{{vm.form | json}}</pre>
</div>
<!-- Put custom templates here -->
<script type="text/ng-template" id="custom-template.html">
<label class="control-label" for="{{::id}}"
uib-popover="{{options.templateOptions.desc}}"
popover-trigger="mouseenter"
popover-placement="top-left"
popover-popup-delay="500"
popover-append-to-body="true">{{to.label}} {{to.required ? '*' : ''}}</label>
<div class="dropdown">
<a class="dropdown-toggle" id="dropdown-{{options.key}}" role="button" data-toggle="dropdown">
<div class="input-group">
<input set-touched="options.formControl" id="{{::id}}" name="{{::id}}" type="text" data-date-time-input="YYYY-MM-DD" class="form-control" data-ng-model="model['date1']"><span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span>
</div>
</a>
<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
<datetimepicker
data-ng-model="model[options.key]"
data-datetimepicker-config="{ dropdownSelector: '#dropdown-' + options.key, minView: 'day', startView: 'year', modelType: 'YYYY-MM-DDTHH:mm:ssZ'}"/>
</ul>
</div>
</script>
<script type="text/ng-template" id="error-messages.html">
<formly-transclude></formly-transclude>
<div ng-messages="fc.$error" ng-if="form.$submitted || options.formControl.$touched" class="error-messages">
<div ng-message="{{ ::name }}" ng-repeat="(name, message) in ::options.validation.messages" class="message">{{ message(fc.$viewValue, fc.$modelValue, this)}}</div>
</div>
<div ng-messages="fc[0].$error" ng-if="form.$submitted || options.formControl[0].$touched" class="error-messages">
<div ng-message="{{ ::name }}" ng-repeat="(name, message) in ::options.validation.messages" class="message">{{ message(fc[0].$viewValue, fc[0].$modelValue, this)}}</div>
</div>
</script>
</body>
</html>
我正在尝试使用 Angular Datetime Picker as a Angular Formly 输入类型。我让它正常工作,这样我就可以编辑和设置一个正确添加到绑定模型的值。
但是,我无法像常规输入字段那样显示验证错误消息。
JS Bin with what I've got so far。如您所见,当您退出该字段时红色不会出现,只有当您尝试提交时才会出现。而且错误消息永远不会出现。
正式配置:
formlyConfigProvider.setType({
name: 'datepicker',
templateUrl: "custom-template.html",
overwriteOk: true,
wrapper: ['bootstrapHasError'],
defaultOptions: function defaultOptions(options) {
return {
templateOptions: {
validation: {
show: true
}
}
};
}
});
formlyConfigProvider.setWrapper({
name: 'validation',
types: ['input', 'datepicker'],
templateUrl: 'error-messages.html'
});
字段
vm.fields = [
{
key: 'text',
type: 'input',
templateOptions: {
label: 'Text',
placeholder: 'Write something',
required: true
},
},
{
key: 'date',
type: 'datepicker',
templateOptions: {
label: 'Date',
placeholder: 'Pick a date',
required: true
},
}
];
模板
<script type="text/ng-template" id="custom-template.html">
<div class="form-group">
<label class="control-label" for="{{::id}}">{{to.label}} {{to.required ? '*' : ''}}</label>
<div class="dropdown">
<a class="dropdown-toggle" id="dropdown-{{options.key}}" role="button" data-toggle="dropdown">
<div class="input-group">
<input id="{{::id}}" name="{{::id}}" type="text" data-date-time-input="YYYY-MM-DD" class="form-control" data-ng-model="model[options.key]"><span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span>
</div>
</a>
<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
<datetimepicker
data-ng-model="model[options.key]"
data-datetimepicker-config="{ dropdownSelector: '#dropdown-' + options.key, minView: 'day', startView: 'year', modelType: 'YYYY-MM-DDTHH:mm:ssZ'}"/>
</ul>
</div>
</div>
</script>
<script type="text/ng-template" id="error-messages.html">
<formly-transclude></formly-transclude>
<div ng-messages="fc.$error" ng-if="form.$submitted || options.formControl.$touched" class="error-messages">
<div ng-message="{{ ::name }}" ng-repeat="(name, message) in ::options.validation.messages" class="message">{{ message(fc.$viewValue, fc.$modelValue, this)}}</div>
</div>
</script>
您应该在 formlyConfigProvider
中 return
您的 validation
而不是将其作为 templateOptions
的值传递。 Return
validation: {
show: true
}
而不是
templateOptions: {
validation: {
show: true
}
}
您的 formlyConfigProvider
应如下所示:
formlyConfigProvider.setType({
name: 'datepicker',
templateUrl: "custom-template.html",
overwriteOk: true,
wrapper: ['bootstrapHasError'],
defaultOptions: function defaultOptions(options) {
return {
validation: {
show: true
}
};
}
});
Here 是工作代码的 JSBin。
深入调查后,我可以看到您使用的控件 Angular Datetime Picker is not fully compatible with Angular Formly。
This is because of the reason that it's overwriting the AngularJS's
ngModelController.$render()
method and hence not setting the value for$touched
like other input controls.Another reason in your code is, the config and the template
error-messages.html
are treating the custom control as single element withfc.$touched
,fc.$error
andfc.$viewValue
whereasDatePicker
is rendering as group of elements (array).
要摆脱所有这些问题,您可以使用自定义指令来设置 $touched
,如下所示,
app.directive('setTouched', function MainCtrl() {
return {
restrict: 'A', // only activate on element attribute
require: '?ngModel', // get a hold of NgModelController
link: function(scope, element, attrs, ngModel) {
if (!ngModel) return; // do nothing if no ng-model
element.on('blur', function() {
var modelControllers = scope.$eval(attrs.setTouched);
if(angular.isArray(modelControllers)) {
angular.forEach(modelControllers, function(modelCntrl) {
modelCntrl.$setTouched();
});
}
});
}
};
});
并且在 custom-template.html
,
<div class="input-group">
<input set-touched="options.formControl" id="{{::id}}" name="{{::id}}" type="text" data-date-time-input="YYYY-MM-DD" class="form-control" data-ng-model="model['date1']"><span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span>
</div>
并在下面的配置中添加 fc[0].$touched
以处理字段数组,
app.run(function run(formlyConfig, formlyValidationMessages) {
formlyConfig.extras.errorExistsAndShouldBeVisibleExpression = 'form.$submitted || fc.$touched || fc[0].$touched';
formlyValidationMessages.addStringMessage('required', 'This field is required');
});
并在 error-messages.html
中添加以下部分以处理字段数组,
<div ng-messages="fc[0].$error" ng-if="form.$submitted || options.formControl[0].$touched" class="error-messages">
<div ng-message="{{ ::name }}" ng-repeat="(name, message) in ::options.validation.messages" class="message">{{ message(fc[0].$viewValue, fc[0].$modelValue, this)}}</div>
</div>
此更改将解决此问题。
正如您在下方显示的错误消息中看到的一些设计问题,
您可以通过删除 div 包装器 <div class="form-group">
、
custom-template.html
,如下所示
<script type="text/ng-template" id="custom-template.html">
<label class="control-label" for="{{::id}}"
uib-popover="{{options.templateOptions.desc}}"
popover-trigger="mouseenter"
popover-placement="top-left"
popover-popup-delay="500"
popover-append-to-body="true">{{to.label}} {{to.required ? '*' : ''}}</label>
<div class="dropdown">
<a class="dropdown-toggle" id="dropdown-{{options.key}}" role="button" data-toggle="dropdown">
<div class="input-group">
<input set-touched="options.formControl" id="{{::id}}" name="{{::id}}" type="text" data-date-time-input="YYYY-MM-DD" class="form-control" data-ng-model="model['date1']"><span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span>
</div>
</a>
<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
<datetimepicker
data-ng-model="model[options.key]"
data-datetimepicker-config="{ dropdownSelector: '#dropdown-' + options.key, minView: 'day', startView: 'year', modelType: 'YYYY-MM-DDTHH:mm:ssZ'}"/>
</ul>
</div>
</script>
我已经用这些更改更新了您的 JSBin。
片段:
/* global angular */
(function() {
'use strict';
var app = angular.module('formlyExample', ['formly', 'formlyBootstrap', 'ngAnimate', 'ngMessages', 'ui.bootstrap.datetimepicker', 'ui.dateTimeInput'], function config(formlyConfigProvider) {
formlyConfigProvider.setType({
name: 'datepicker',
templateUrl: "custom-template.html",
overwriteOk: true,
wrapper: ['bootstrapHasError'],
defaultOptions: function defaultOptions(options) {
return {
templateOptions: {
validation: {
show: true
}
}
};
}
});
formlyConfigProvider.setWrapper({
name: 'validation',
types: ['input', 'datepicker'],
templateUrl: 'error-messages.html'
});
});
app.run(function run(formlyConfig, formlyValidationMessages) {
formlyConfig.extras.errorExistsAndShouldBeVisibleExpression = 'form.$submitted || fc.$touched || fc[0].$touched';
formlyValidationMessages.addStringMessage('required', 'This field is required');
});
app.directive('setTouched', function MainCtrl() {
return {
restrict: 'A', // only activate on element attribute
require: '?ngModel', // get a hold of NgModelController
link: function(scope, element, attrs, ngModel) {
if (!ngModel) return; // do nothing if no ng-model
element.on('blur', function() {
var modelControllers = scope.$eval(attrs.setTouched);
if(angular.isArray(modelControllers)) {
angular.forEach(modelControllers, function(modelCntrl) {
modelCntrl.$setTouched();
});
}
});
}
};
});
app.controller('MainCtrl', function MainCtrl(formlyVersion) {
var vm = this;
vm.onSubmit = onSubmit;
vm.model = {};
vm.options = {};
vm.env = {
angularVersion: angular.version.full,
formlyVersion: formlyVersion
};
vm.fields = [
{
key: 'text',
type: 'input',
templateOptions: {
label: 'Text',
placeholder: 'Write something',
required: true
},
},
{
key: 'moretext',
type: 'input',
templateOptions: {
label: 'More Text',
placeholder: 'Write something else',
},
},
{
key: 'date',
type: 'datepicker',
templateOptions: {
label: 'Date',
placeholder: 'Pick a date',
required: true
},
}
];
vm.originalFields = angular.copy(vm.fields);
// function definition
function onSubmit() {
if (vm.form.$valid) {
vm.options.updateInitialValue();
alert(JSON.stringify(vm.model), null, 2);
}
}
});
})();
body {
margin: 20px
}
.formly-field {
margin-bottom: 30px;
}
.error-messages {
position: relative;
}
.error-messages, .message {
opacity: 1;
transition: .3s linear all;
}
.message {
font-size: .8em;
position: absolute;
width: 100%;
color: #a94442;
margin-top: 4px;
}
.error-messages.ng-enter.ng-enter-active,
.message.ng-enter.ng-enter-active {
opacity: 1;
top: 0;
}
.error-messages.ng-enter,
.message.ng-enter {
opacity: 0;
top: -10px;
}
.error-messages.ng-leave,
.message.ng-leave {
opacity: 1;
top: 0;
}
.error-messages.ng-leave-active,
.message.ng-leave-active {
opacity: 0;
top: -10px;
}
<!DOCTYPE html>
<html>
<head>
<!-- jQuery -->
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<!-- Twitter bootstrap -->
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.css" rel="stylesheet">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<!-- apiCheck is used by formly to validate its api -->
<script src="//npmcdn.com/api-check@latest/dist/api-check.js"></script>
<!-- This is the latest version of angular (at the time this template was created) -->
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.js"></script>
<!-- This is the latest version of formly core. -->
<script src="//npmcdn.com/angular-formly@latest/dist/formly.js"></script>
<!-- This is the latest version of formly bootstrap templates -->
<script src="//npmcdn.com/angular-formly-templates-bootstrap@latest/dist/angular-formly-templates-bootstrap.js"></script>
<script src="https://rawgit.com/angular/bower-angular-messages/v1.4.4/angular-messages.js"></script>
<script src="https://rawgit.com/angular/bower-angular-animate/v1.4.4/angular-animate.js"></script>
<!-- Moment -->
<script src="https://cdn.rawgit.com/moment/moment/develop/min/moment-with-locales.min.js"></script>
<!-- Datetime picker -->
<script type="text/javascript" src="https://cdn.rawgit.com/dalelotts/angular-bootstrap-datetimepicker/master/src/js/datetimepicker.js"></script>
<script type="text/javascript" src="https://cdn.rawgit.com/dalelotts/angular-bootstrap-datetimepicker/master/src/js/datetimepicker.templates.js"></script>
<link href="https://cdn.rawgit.com/dalelotts/angular-bootstrap-datetimepicker/master/src/css/datetimepicker.css" rel="stylesheet">
<script type="text/javascript" src="https://cdn.rawgit.com/dalelotts/angular-date-time-input/master/src/dateTimeInput.js"></script>
<title>Angular Formly Example</title>
</head>
<body ng-app="formlyExample" ng-controller="MainCtrl as vm">
<div>
<form ng-submit="vm.onSubmit()" name="vm.form" novalidate>
<formly-form model="vm.model" fields="vm.fields" options="vm.options" form="vm.form">
<button type="submit" class="btn btn-primary submit-button">Submit</button>
<button type="button" class="btn btn-default" ng-click="vm.options.resetModel()">Reset</button>
</formly-form>
</form>
<hr />
<h2>Model</h2>
<pre>{{vm.model | json}}</pre>
<h2>Fields <small>(note, functions are not shown)</small></h2>
<pre>{{vm.originalFields | json}}</pre>
<h2>Form</h2>
<pre>{{vm.form | json}}</pre>
</div>
<!-- Put custom templates here -->
<script type="text/ng-template" id="custom-template.html">
<label class="control-label" for="{{::id}}"
uib-popover="{{options.templateOptions.desc}}"
popover-trigger="mouseenter"
popover-placement="top-left"
popover-popup-delay="500"
popover-append-to-body="true">{{to.label}} {{to.required ? '*' : ''}}</label>
<div class="dropdown">
<a class="dropdown-toggle" id="dropdown-{{options.key}}" role="button" data-toggle="dropdown">
<div class="input-group">
<input set-touched="options.formControl" id="{{::id}}" name="{{::id}}" type="text" data-date-time-input="YYYY-MM-DD" class="form-control" data-ng-model="model['date1']"><span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span>
</div>
</a>
<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
<datetimepicker
data-ng-model="model[options.key]"
data-datetimepicker-config="{ dropdownSelector: '#dropdown-' + options.key, minView: 'day', startView: 'year', modelType: 'YYYY-MM-DDTHH:mm:ssZ'}"/>
</ul>
</div>
</script>
<script type="text/ng-template" id="error-messages.html">
<formly-transclude></formly-transclude>
<div ng-messages="fc.$error" ng-if="form.$submitted || options.formControl.$touched" class="error-messages">
<div ng-message="{{ ::name }}" ng-repeat="(name, message) in ::options.validation.messages" class="message">{{ message(fc.$viewValue, fc.$modelValue, this)}}</div>
</div>
<div ng-messages="fc[0].$error" ng-if="form.$submitted || options.formControl[0].$touched" class="error-messages">
<div ng-message="{{ ::name }}" ng-repeat="(name, message) in ::options.validation.messages" class="message">{{ message(fc[0].$viewValue, fc[0].$modelValue, this)}}</div>
</div>
</script>
</body>
</html>