इस गहरी जांच के बाद, मैं देख सकता हूं कि आपने Angular Datetime Picker पर नियंत्रण को Angular Formly के साथ पूरी तरह से संगत नहीं किया है।
यही कारण है यह AngularJS के ngModelController.$render()
विधि को अधिलेखित है और इसलिए अन्य इनपुट नियंत्रण की तरह $touched
के लिए मूल्य की स्थापना नहीं है कि के कारण है।
अपने कोड में एक और कारण है, config और टेम्पलेट error-messages.html
fc.$touched
, fc.$error
और fc.$viewValue
जबकि DatePicker
तत्वों (सरणी) के समूह के रूप में प्रदर्शित हो रहा है साथ ही तत्व के रूप में कस्टम नियंत्रण इलाज कर रहे हैं।
इन सभी मुद्दों से छुटकारा पाने के लिए, आप के रूप में नीचे $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/[email protected]/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/[email protected]/dist/formly.js"></script>
<!-- This is the latest version of formly bootstrap templates -->
<script src="//npmcdn.com/[email protected]/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>
आप मुद्दा व्याख्या कर सकते हैं थोड़ा और अगर मैं लेबल "पाठ" के साथ पहली बार पाठ बॉक्स क्लिक करें और अगले पाठ बॉक्स "अधिक पाठ" पर क्लिक करें के बाद से, पहला टेक्स्टबॉक्स क्रोम में एक सत्यापन त्रुटि दिखाता है। लेकिन यह "तिथि" के लिए नहीं हो रहा है। क्या यह मुद्दा है? – Aruna
हां, यह समस्या –
है क्या आप मेरा नीचे जवाब देख सकते हैं? – Aruna