Firefox中input type datetime-local不显示日期选择器问题求助
我懂你这个痛点——Firefox一直对原生datetime-local控件支持不太友好,直到近年的新版本才开始有限支持,旧版本直接就显示成普通文本框,确实头疼。试过Modernizr没解决也正常,因为它只是做兼容性检测,不会自动给你补全替代方案。下面给你几个实用的解决办法,按推荐程度排序:
方案1:用第三方日期时间选择器库(最省心)
原生控件兼容性拉胯,不如直接上成熟的第三方库,既能保证跨浏览器一致性,还能自定义样式。针对你的Angular项目,推荐两个选项:
选项A:Angular UI Bootstrap 组合控件
它的Datepicker和Timepicker可以组合成日期时间选择器,适配所有主流浏览器:
- 先引入Bootstrap和Angular UI Bootstrap的依赖到项目中
- 替换原生
input为组合控件,同时在控制器里处理日期格式转换(因为datetime-local要求ISO 8601格式,比如2024-05-20T14:30)
示例代码:
<div class="form-group" ng-class="{'has-error': vm.basicInfoForm.validFrom.$invalid && (vm.basicInfoForm.validFrom.$dirty || vm.basicInfoForm.$submitted)}"> <label translate>.NEW.STARTDATE</label> <!-- 日期选择器 --> <p class="input-group"> <input type="text" class="form-control" uib-datepicker-popup="yyyy-MM-dd" ng-model="vm.basicInfo.validFromDate" is-open="vm.datePickerOpened" datepicker-options="vm.dateOptions" ng-required="true" close-text="Close" /> <span class="input-group-btn"> <button type="button" class="btn btn-default" ng-click="vm.openDatePicker($event)"> <i class="glyphicon glyphicon-calendar"></i> </button> </span> </p> <!-- 时间选择器 --> <p class="input-group mt-2"> <input type="text" class="form-control" uib-timepicker ng-model="vm.basicInfo.validFromTime" hour-step="1" minute-step="15" show-meridian="false" /> </p> <span class="help-block error-block basic-block" translate>.NEW.CHECKDATE</span> </div>
控制器里的逻辑:
vm.openDatePicker = function($event) { $event.preventDefault(); $event.stopPropagation(); vm.datePickerOpened = true; }; vm.dateOptions = { formatYear: 'yy', startingDay: 1 }; // 监听日期和时间的变化,合并成符合要求的ISO格式字符串 $scope.$watchGroup(['vm.basicInfo.validFromDate', 'vm.basicInfo.validFromTime'], function(newValues) { const selectedDate = newValues[0]; const selectedTime = newValues[1]; if (selectedDate && selectedTime) { const year = selectedDate.getFullYear(); const month = String(selectedDate.getMonth() + 1).padStart(2, '0'); const day = String(selectedDate.getDate()).padStart(2, '0'); const hours = String(selectedTime.getHours()).padStart(2, '0'); const minutes = String(selectedTime.getMinutes()).padStart(2, '0'); vm.basicInfo.validFrom = `${year}-${month}-${day}T${hours}:${minutes}`; } });
选项B:Flatpickr(轻量无依赖)
这是个轻量级的选择器库,支持Angular指令,直接替换原生input就能用,自动处理格式和兼容性:
- 引入Flatpickr的CSS和JS文件
- 给input添加指令配置:
<div class="form-group" ng-class="{'has-error': vm.basicInfoForm.validFrom.$invalid && (vm.basicInfoForm.validFrom.$dirty || vm.basicInfoForm.$submitted)}"> <label translate>.NEW.STARTDATE</label> <input type="text" class="form-control" ng-model="vm.basicInfo.validFrom" flatpickr="{ enableTime: true, dateFormat: 'Y-m-dTH:i' }" /> <span class="help-block error-block basic-block" translate>.NEW.CHECKDATE</span> </div>
它的输出格式和datetime-local要求的完全一致,不用额外做格式转换,非常省心。
方案2:检测浏览器支持并降级(不想用第三方库的话)
如果坚持想用原生控件,可以手动检测浏览器是否支持datetime-local,不支持就替换成分开的date和time控件,最后合并值:
- 先写个检测函数:
function supportsDatetimeLocal() { const testInput = document.createElement('input'); testInput.type = 'datetime-local'; // 检测类型是否保留,且支持valueAsDate属性 return testInput.type === 'datetime-local' && typeof testInput.valueAsDate === 'object'; }
- 在视图里根据检测结果切换控件:
<div class="form-group" ng-class="{'has-error': vm.basicInfoForm.$invalid && (vm.basicInfoForm.$dirty || vm.basicInfoForm.$submitted)}"> <label translate>.NEW.STARTDATE</label> <!-- 支持datetime-local的浏览器显示原生控件 --> <div ng-if="vm.supportsDatetimeLocal"> <input type="datetime-local" name="validFrom" class="form-control" ng-model="vm.basicInfo.validFrom"/> </div> <!-- 不支持的浏览器显示分开的日期和时间控件 --> <div ng-if="!vm.supportsDatetimeLocal"> <input type="date" name="validFromDate" class="form-control mb-2" ng-model="vm.basicInfo.validFromDate" ng-required="true"/> <input type="time" name="validFromTime" class="form-control" ng-model="vm.basicInfo.validFromTime" ng-required="true"/> </div> <span class="help-block error-block basic-block" translate>.NEW.CHECKDATE</span> </div>
- 控制器里处理合并逻辑:
vm.supportsDatetimeLocal = supportsDatetimeLocal(); // 合并日期和时间到validFrom字段 $scope.$watchGroup(['vm.basicInfo.validFromDate', 'vm.basicInfo.validFromTime'], function(newValues) { if (!vm.supportsDatetimeLocal) { const date = newValues[0]; const time = newValues[1]; if (date && time) { vm.basicInfo.validFrom = `${date}T${time}`; } } });
这样Chrome用户会看到原生的日期时间选择器,Firefox用户则看到分开的日期和时间选择器,都能正常输入并提交符合格式的值。
内容的提问来源于stack exchange,提问作者Nidhin Kumar




