angularjs - uib - El formato de fecha datepicker de bootstrap angular no formatea el valor ng-model
uib-pagination angularjs (13)
Aunque se han publicado respuestas similares, me gustaría contribuir a lo que me pareció la solución más fácil y limpia. Suponiendo que está utilizando el selector de fecha AngularUI y su valor inicial para el modelo ng no se formatea simplemente agregando la siguiente directiva a su proyecto para solucionar el problema:
angular.module(''yourAppName'')
.directive(''datepickerPopup'', function (){
return {
restrict: ''EAC'',
require: ''ngModel'',
link: function(scope, element, attr, controller) {
//remove the default formatter from the input directive to prevent conflict
controller.$formatters.shift();
}
}
});
Encontré esta solución en los problemas de Github AngularUI y, por lo tanto, todo el crédito va a la gente de allí.
Estoy usando el recolector de fecha de arranque en mi aplicación angular. Sin embargo, cuando selecciono una fecha de ese selector de fechas subyacente, el modelo ng que tengo enlazar se actualiza. Quiero que ese modelo ng tenga un formato de fecha ''MM / dd / aaaa''. Pero cada vez que hace cita como esta
"2009-02-03T18:30:00.000Z"
en lugar de
02/04/2009
He creado un plunkr para el mismo enlace plunkr
Mi código HTML y controlador es como abajo
<!doctype html>
<html ng-app="plunker">
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.js"></script>
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.11.0.js"></script>
<script src="example.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div ng-controller="DatepickerDemoCtrl">
<pre>Selected date is: <em>{{dt | date:''MM/dd/yyyy'' }}</em></pre>
<p>above filter will just update above UI but I want to update actual ng-modle</p>
<h4>Popup</h4>
<div class="row">
<div class="col-md-6">
<p class="input-group">
<input type="text" class="form-control"
datepicker-popup="{{format}}"
ng-model="dt"
is-open="opened" min-date="minDate"
max-date="''2015-06-22''"
datepicker-options="dateOptions"
date-disabled="disabled(date, mode)"
ng-required="true" close-text="Close" />
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="open($event)">
<i class="glyphicon glyphicon-calendar"></i></button>
</span>
</p>
</div>
</div>
<!--<div class="row">
<div class="col-md-6">
<label>Format:</label> <select class="form-control" ng-model="format" ng-options="f for f in formats"><option></option></select>
</div>
</div>-->
<hr />
{{dt}}
</div>
</body>
</html>
Controlador angular
angular.module(''plunker'', [''ui.bootstrap'']);
var DatepickerDemoCtrl = function ($scope) {
$scope.open = function($event) {
$event.preventDefault();
$event.stopPropagation();
$scope.opened = true;
};
$scope.dateOptions = {
formatYear: ''yy'',
startingDay: 1
};
$scope.format = ''dd-MMMM-yyyy'';
};
Gracias de antemano por revisar mi pregunta.
ACTUALIZAR
Estoy llamando al siguiente método para publicar mis datos y VAR es una matriz de tamaño 900 que contiene variables de selección de fecha.
public SaveCurrentData(formToSave: tsmodels.ResponseTransferCalculationModelTS) {
var query = this.EntityQuery.from(''SaveFormData'').withParameters({
$method: ''POST'',
$encoding: ''JSON'',
$data: {
VAR: formToSave.VAR,
X: formToSave.X,
CurrentForm: formToSave.currentForm,
}
});
var deferred = this.q.defer();
this.manager.executeQuery(query).then((response) => {
deferred.resolve(response);
}, (error) => {
deferred.reject(error);
});
return deferred.promise;
}
Con tantas respuestas ya escritas, Aquí está mi opinión.
Con Angular 1.5.6 y ui-bootstrap 1.3.3, simplemente agregue esto en el modelo y listo.
ng-model-options="{timezone: ''UTC''}"
Nota : use esto solo si le preocupa que la fecha se haya retrasado 1 día y no se haya molestado con el tiempo adicional de T00: 00: 00.000Z
Plunkr actualizado aquí:
Definir una nueva directiva para solucionar un error no es realmente ideal.
Debido a que el selector de fecha muestra las fechas posteriores correctamente, una solución simple podría ser establecer primero la variable del modelo en nulo, y luego a la fecha actual después de un tiempo:
$scope.dt = null;
$timeout( function(){
$scope.dt = new Date();
},100);
Después de revisar las respuestas anteriores, se me ocurrió esto y funcionó perfectamente sin tener que agregar un atributo adicional a su marca
angular.module(''app'').directive(''datepickerPopup'', function(dateFilter) {
return {
restrict: ''EAC'',
require: ''ngModel'',
link: function(scope, element, attr, ngModel) {
ngModel.$parsers.push(function(viewValue) {
return dateFilter(viewValue, ''yyyy-MM-dd'');
});
}
}
});
El format
especificado a través de datepicker-popup
es solo el formato para la fecha mostrada . El ngModel
subyacente es un objeto Date. Si intenta mostrarlo, se mostrará como es el estándar, se trata de una interpretación compatible con el estándar.
Puede mostrarlo como desee utilizando el filtro de date
en la vista o, si necesita que se lo analice en el controlador, puede inyectar $filter
en su controlador y llamarlo como $filter(''date'')(date, format)
. Véase también la fecha filtro de documentos .
Finalmente conseguí una gran solución al problema anterior. La correa angular tiene exactamente la misma característica que estoy esperando. Simplemente aplicando date-format="MM/dd/yyyy" date-type="string"
obtuve mi comportamiento esperado de actualizar el modelo ng en un formato dado.
<div class="bs-example" style="padding-bottom: 24px;" append-source>
<form name="datepickerForm" class="form-inline" role="form">
<!-- Basic example -->
<div class="form-group" ng-class="{''has-error'': datepickerForm.date.$invalid}">
<label class="control-label"><i class="fa fa-calendar"></i> Date <small>(as date)</small></label>
<input type="text" autoclose="true" class="form-control" ng-model="selectedDate" name="date" date-format="MM/dd/yyyy" date-type="string" bs-datepicker>
</div>
<hr>
{{selectedDate}}
</form>
</div>
Aquí está trabajando link plunk
La directiva datepicker (y datepicker-popup) requiere que el modelo ng sea un objeto Date. Esto está documentado here .
Si desea que ng-model sea una cadena en un formato específico, debe crear una directiva de envoltorio. Aquí hay un ejemplo ( Plunker ):
(function () {
''use strict'';
angular
.module(''myExample'', [''ngAnimate'', ''ngSanitize'', ''ui.bootstrap''])
.controller(''MyController'', MyController)
.directive(''myDatepicker'', myDatepickerDirective);
MyController.$inject = [''$scope''];
function MyController ($scope) {
$scope.dateFormat = ''dd MMMM yyyy'';
$scope.myDate = ''30 Jun 2017'';
}
myDatepickerDirective.$inject = [''uibDateParser'', ''$filter''];
function myDatepickerDirective (uibDateParser, $filter) {
return {
restrict: ''E'',
scope: {
name: ''@'',
dateFormat: ''@'',
ngModel: ''=''
},
required: ''ngModel'',
link: function (scope) {
var isString = angular.isString(scope.ngModel) && scope.dateFormat;
if (isString) {
scope.internalModel = uibDateParser.parse(scope.ngModel, scope.dateFormat);
} else {
scope.internalModel = scope.ngModel;
}
scope.open = function (event) {
event.preventDefault();
event.stopPropagation();
scope.isOpen = true;
};
scope.change = function () {
if (isString) {
scope.ngModel = $filter(''date'')(scope.internalModel, scope.dateFormat);
} else {
scope.ngModel = scope.internalModel;
}
};
},
template: [
''<div class="input-group">'',
''<input type="text" readonly="true" style="background:#fff" name="{{name}}" class="form-control" uib-datepicker-popup="{{dateFormat}}" ng-model="internalModel" is-open="isOpen" ng-click="open($event)" ng-change="change()">'',
''<span class="input-group-btn">'',
''<button class="btn btn-default" ng-click="open($event)"> <i class="glyphicon glyphicon-calendar"></i> </button>'',
''</span>'',
''</div>''
].join('''')
}
}
})();
<!DOCTYPE html>
<html>
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular-animate.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular-sanitize.js"></script>
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-2.5.0.js"></script>
<script src="example.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body ng-app="myExample">
<div ng-controller="MyController">
<p>
Date format: {{dateFormat}}
</p>
<p>
Value: {{myDate}}
</p>
<p>
<my-datepicker ng-model="myDate" date-format="{{dateFormat}}"></my-datepicker>
</p>
</div>
</body>
</html>
Me encontré con el mismo problema y, después de un par de horas de registro e investigación, lo solucioné.
Resultó que, por primera vez, el valor se establece en un selector de fecha, $ viewValue es una cadena, por lo que el dateFilter lo muestra como está. Todo lo que hice es analizarlo en un objeto Date.
Busca ese bloque en el archivo ui-bootstrap-tpls
ngModel.$render = function() {
var date = ngModel.$viewValue ? dateFilter(ngModel.$viewValue, dateFormat) : '''';
element.val(date);
updateCalendar();
};
y reemplazarlo por:
ngModel.$render = function() {
ngModel.$viewValue = new Date(ngModel.$viewValue);
var date = ngModel.$viewValue ? dateFilter(ngModel.$viewValue, dateFormat) : '''';
element.val(date);
updateCalendar();
};
Esperemos que esto ayude :)
Pasos para cambiar el formato de fecha predeterminado de ng-model
Para diferentes formatos de fecha, compruebe los valores del formato de fecha del selector de fecha de jqueryui aquí, por ejemplo, he usado dd / mm / aa
Crear directiva angularjs.
angular.module(''app'', [''ui.bootstrap'']).directive(''dt'', function () {
return {
restrict: ''EAC'',
require: ''ngModel'',
link: function (scope, element, attr, ngModel) {
ngModel.$parsers.push(function (viewValue) {
return dateFilter(viewValue, ''dd/mm/yy'');
});
}
}
});
Escribir la función dateFilter
function dateFilter(val,format) {
return $.datepicker.formatDate(format,val);
}
En la página html escribe el atributo ng-modal
<input type="text" class="form-control" date-type="string" uib-datepicker-popup="{{format}}" ng-model="src.pTO_DATE" is-open="popup2.opened" datepicker-options="dateOptions" ng-required="true" close-text="Close" show-button-bar="false" show-weeks="false" dt />
Puede usar formateadores después de elegir el valor dentro de su directiva datepicker. Por ejemplo
angular.module(''foo'').directive(''bar'', function() {
return {
require: ''?ngModel'',
link: function(scope, elem, attrs, ctrl) {
if (!ctrl) return;
ctrl.$formatters.push(function(value) {
if (value) {
// format and return date here
}
return undefined;
});
}
};
});
Puedes usar $ parsers como se muestra a continuación, esto lo resolvió para mí.
window.module.directive(''myDate'', function(dateFilter) {
return {
restrict: ''EAC'',
require: ''?ngModel'',
link: function(scope, element, attrs, ngModel) {
ngModel.$parsers.push(function(viewValue) {
return dateFilter(viewValue,''yyyy-MM-dd'');
});
}
};
});
HTML:
<p class="input-group datepicker" >
<input
type="text"
class="form-control"
name="name"
datepicker-popup="yyyy-MM-dd"
date-type="string"
show-weeks="false"
ng-model="data[$parent.editable.name]"
is-open="$parent.opened"
min-date="minDate"
close-text="Close"
ng-required="{{editable.mandatory}}"
show-button-bar="false"
close-on-date-selection="false"
my-date />
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="openDatePicker($event)">
<i class="glyphicon glyphicon-calendar"></i>
</button>
</span>
</p>
Puedo arreglar esto agregando el siguiente código en mi archivo JSP. Ahora tanto el modelo como los valores de UI son iguales.
<div ng-show="false">
{{dt = (dt | date:''dd-MMMM-yyyy'') }}
</div>
Todas las soluciones propuestas no funcionaron para mí, pero la más cercana fue de @Rishii.
Estoy usando AngularJS 1.4.4 y UI Bootstrap 0.13.3.
.directive(''jsr310Compatible'', [''dateFilter'', ''dateParser'', function(dateFilter, dateParser) {
return {
restrict: ''EAC'',
require: ''ngModel'',
priority: 1,
link: function(scope, element, attrs, ngModel) {
var dateFormat = ''yyyy-MM-dd'';
ngModel.$parsers.push(function(viewValue) {
return dateFilter(viewValue, dateFormat);
});
ngModel.$validators.date = function (modelValue, viewValue) {
var value = modelValue || viewValue;
if (!attrs.ngRequired && !value) {
return true;
}
if (angular.isNumber(value)) {
value = new Date(value);
}
if (!value) {
return true;
}
else if (angular.isDate(value) && !isNaN(value)) {
return true;
}
else if (angular.isString(value)) {
var date = dateParser.parse(value, dateFormat);
return !isNaN(date);
}
else {
return false;
}
};
}
};
}])