我有一个 mongoose 连接到包含集合中Date对象的数据库。我想使用Angular Material的DatePicker
控件来查看这些Date对象。 Date对象遵循 ISO字符串格式。
以下是代码段:
<md-datepicker
ng-model="license.expirationdate" md-placeholder="Enter date">
</md-datepicker>
我收到以下错误:
ng-model
的{{1}}必须是日期实例。
在研究时,我发现您可以使用过滤器来创建Date实例,但这对我不起作用 - &gt;我收到一条错误消息,指出使用简单过滤器时模型值是不可分配的。过滤器只是根据字符串输入返回一个新的Date对象。
如何将字符串格式化为Date对象,同时仍允许进行md-datepicker
更改?
编辑:mongoose的架构 var Schema = mongoose.Schema;
ng-model
这是填充架构的快速路由
var Schema = mongoose.Schema;
var modelschema = new Schema({
name : String,
licensetype : String,
activationcount : Number,
expirationdate: Date,
key : String
})
答案 0 :(得分:16)
以下是一个例子:
标记:
<div ng-controller="MyCtrl">
<md-datepicker ng-model="dt" md-placeholder="Enter date" ng-change="license.expirationdate = dt.toISOString()">
</md-datepicker>
{{license.expirationdate}}
</div>
JavaScript的:
app.controller('MyCtrl', function($scope) {
$scope.license = {
expirationdate: '2015-12-15T23:00:00.000Z'
};
$scope.dt = new Date($scope.license.expirationdate);
});
小提琴:http://jsfiddle.net/masa671/jm6y12un/
更新:
使用ng-repeat
:
标记:
<div ng-controller="MyCtrl">
<div ng-repeat="d in data">
<md-datepicker
ng-model="dataMod[$index].dt"
md-placeholder="Enter date"
ng-change="d.license.expirationdate = dataMod[$index].dt.toISOString()">
</md-datepicker>
{{d.license.expirationdate}}
</div>
</div>
JavaScript的:
app.controller('MyCtrl', function($scope) {
var i;
$scope.data = [
{ license:
{ expirationdate: '2015-12-15T23:00:00.000Z' }
},
{ license:
{ expirationdate: '2015-12-20T23:00:00.000Z' }
},
{ license:
{ expirationdate: '2015-12-25T23:00:00.000Z' }
}
];
$scope.dataMod = [];
for (i = 0; i < $scope.data.length; i += 1) {
$scope.dataMod.push({
dt: new Date($scope.data[i].license.expirationdate)
});
}
});
答案 1 :(得分:10)
您可以使用ng-init,自定义过滤器和ng-change,并在标记中完成此操作。
JavaScript的:
app.filter('toDate', function() {
return function(input) {
return new Date(input);
}
})
HTML:
<md-datepicker
ng-init="date = (license.expirationdate | toDate)"
ng-model="date"
ng-change="license.expirationdate = date.toISOString()"
md-placeholder="Enter date">
</md-datepicker>
使用这种方法,您不需要使用View逻辑来混淆Controller代码。缺点是Controller中对license.expirationdate的任何编程更改都不会自动反映在View中。
答案 2 :(得分:8)
http://jsfiddle.net/katfby9L/1/
--------- beginning of crash
06-23 11:19:56.985 2466-2466/com.candyx.sims E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.candyx.sims, PID: 2466
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v7.widget.RecyclerView.setLayoutManager(android.support.v7.widget.RecyclerView$LayoutManager)' on a null object reference
at com.candyx.sims.BlankFragment.onCreateView(BlankFragment.java:38)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:1974)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1252)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:742)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1617)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:517)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
06-23 11:23:14.912 5839-5873/com.candyx.sims D/OpenGLRenderer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true
[ 06-23 11:23:14.920 5839: 5839 D/ ]
HostConnection::get() New Host Connection established 0xb4125190, tid 5839
06-23 11:23:14.927 5839-5839/com.candyx.sims D/Atlas: Validating map...
06-23 11:23:15.011 5839-5873/com.candyx.sims I/OpenGLRenderer: Initialized EGL, version 1.4
06-23 11:23:15.027 5839-5873/com.candyx.sims D/OpenGLRenderer: Enabling debug mode 0
06-23 11:23:15.039 5839-5873/com.candyx.sims W/EGL_emulation: eglSurfaceAttrib not implemented
06-23 11:23:15.039 5839-5873/com.candyx.sims W/OpenGLRenderer: Failed to set EGL_SWAP_BEHAVIOR on surface 0xae838600, error=EGL_SUCCESS
06-23 11:23:16.444 5839-5839/com.candyx.sims W/PathParser: Points are too far apart 4.000000596046461
06-23 11:23:17.342 5839-5839/com.candyx.sims W/PathParser: Points are too far apart 4.000000596046461
06-23 11:23:17.350 5839-5839/com.candyx.sims I/AppCompatViewInflater: app:theme is now deprecated. Please move to using android:theme instead.
06-23 11:23:17.369 5839-5839/com.candyx.sims D/AndroidRuntime: Shutting down VM
06-23 11:23:17.369 5839-5839/com.candyx.sims E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.candyx.sims, PID: 5839
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v7.widget.RecyclerView.setLayoutManager(android.support.v7.widget.RecyclerView$LayoutManager)' on a null object reference
at com.candyx.sims.NewFragment.onCreateView(NewFragment.java:38)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:1974)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1252)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:742)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1617)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:517)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
06-23 11:25:16.961 7518-7518/com.candyx.sims W/art: Before Android 4.1, method android.graphics.PorterDuffColorFilter android.support.graphics.drawable.VectorDrawableCompat.updateTintFilter(android.graphics.PorterDuffColorFilter, android.content.res.ColorStateList, android.graphics.PorterDuff$Mode) would have incorrectly overridden the package-private method in android.graphics.drawable.Drawable
06-23 11:25:17.078 7518-7548/com.candyx.sims D/OpenGLRenderer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true
[ 06-23 11:25:17.081 7518: 7518 D/ ]
HostConnection::get() New Host Connection established 0xb412a1f0, tid 7518
06-23 11:25:17.082 7518-7518/com.candyx.sims D/Atlas: Validating map...
06-23 11:25:17.109 7518-7548/com.candyx.sims I/OpenGLRenderer: Initialized EGL, version 1.4
06-23 11:25:17.126 7518-7548/com.candyx.sims D/OpenGLRenderer: Enabling debug mode 0
06-23 11:25:17.134 7518-7548/com.candyx.sims W/EGL_emulation: eglSurfaceAttrib not implemented
06-23 11:25:17.134 7518-7548/com.candyx.sims W/OpenGLRenderer: Failed to set EGL_SWAP_BEHAVIOR on surface 0xb41234c0, error=EGL_SUCCESS
06-23 11:25:31.030 7518-7518/com.candyx.sims W/PathParser: Points are too far apart 4.000000596046461
06-23 11:25:32.174 7518-7518/com.candyx.sims W/PathParser: Points are too far apart 4.000000596046461
06-23 11:25:32.187 7518-7518/com.candyx.sims I/AppCompatViewInflater: app:theme is now deprecated. Please move to using android:theme instead.
06-23 11:25:32.207 7518-7518/com.candyx.sims D/AndroidRuntime: Shutting down VM
06-23 11:25:32.207 7518-7518/com.candyx.sims E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.candyx.sims, PID: 7518
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v7.widget.RecyclerView.setLayoutManager(android.support.v7.widget.RecyclerView$LayoutManager)' on a null object reference
at com.candyx.sims.NewFragment.onCreateView(NewFragment.java:38)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:1974)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1252)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:742)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1617)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:517)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
这会自动将服务器JSON响应中的所有字符串转换为日期
答案 3 :(得分:7)
我会这样做:
HTML:
<div ng-controller="MyCtrl">
<div ng-repeat="d in data">
<md-datepicker
ng-init="date = StrToDate(d.license.expirationdate);"
ng-model="date"
md-placeholder="Enter date"
ng-change="d.license.expirationdate = date.toISOString()">
</md-datepicker>
{{d.license.expirationdate}}
</div>
</div>
在您的控制器中
$scope.StrToDate = function (str) {
return new Date(str);
}
答案 4 :(得分:1)
我必须从当天起默认日期为6个月......
经过相当长的日期转换为ISO格式的实验后,我创建了一个我在这里找不到的简单解决方案。
总体思路:今天花些时间,加上/减去时间,以毫秒为单位,直到所需日期为止。
HTML:
<div flex-gt-xs>
<h4 class="md-title">Date From:</h4>
<md-datepicker ng-model="vm.sixMonthBeforeNow" md-placeholder="Date From:"></md-datepicker>
{{vm.sixMonthBeforeNow}}
</div>
控制器:
vm.sixMonthBeforeNow = new Date((+new Date) - 15778800000); // today - 6 month in ISO format (native for Angular Material Datepicker)
也许这对某人有用......
答案 5 :(得分:0)
我创建了一个自定义指令来为我处理这个问题。我使用了Sugarjs.com中的Date类,以便它可以像我实现它一样工作。此方法可确保日期始终显示为日期,并且不会因涉及UTC偏移而跳转。如果您不想限制为UTC,可以将格式化程序更改为return new Date(input)
。
angular.module 'app.components'
.directive 'autoChangeStringDates', ->
directive =
restrict: 'A'
require: 'ngModel'
priority: 2000
link: (scope, el, attrs, ngModelController) ->
ngModelController.$formatters.push((input) ->
if typeof input == Date
return input
else
return Date.create(input, {fromUTC: true})
)
return
然后在HTML标记中使用它,如此
<md-datepicker ng-model='myModel' auto-change-string-dates></md-datepicker>