我是Angular JS的新手,我正在尝试创建一个datepicker指令。它不会像Angular UI Bootstrap datepicker那样工作,因为它不会使用文本框,而是使用整页日历,您可以轻扫并点击一天(这将更新ngModel)。
我的计划是拥有一个具有renderMonth()函数的指令。此函数将接受一个月作为参数,并生成数组中的所有行/天,然后绑定到该月的模板。
我的问题是我可以在我的指令声明中为datepicker指定一个模板,但我不知道如何为行/天等指定模板并加载它们并绑定它们。我可以使用jQuery和大量的字符串集合来做到这一点,但这似乎都是错误的。
我一直在阅读Angular UI Datepicker的源代码,但作为一个新手,它对我来说没什么意义。他们已将所有内容分解为许多子指令(月指令,年份指令等),并且他们有自己的模板,但这不是我想要做的,因为我的Angular技能不会延伸到创建与每个通信的指令其他。 Angular UI代码对我来说太复杂了。
我喜欢的一件事是他们在模板中使用现有的指令,例如ng-repeat,并将它们绑定到数组或行/天。对我来说,我需要在每次调用renderMonth()时加载模板并编译模板,因为它中有现有的指令。
所以,基本上我的问题是,是否有人有任何关于如何将模板导入我的渲染函数,编译它并将其绑定到我的指令范围内的行/日数据的示例。
我会说实话。我不知道我是否说出任何意义。我只是输入听起来含糊不清的单词。
我需要的是有人指出我正确的方向。感谢。
答案 0 :(得分:4)
正如评论中所讨论的,我个人不会过分担心导入模板,$compile
函数或任何复杂的相对简单的标记。
我已经创建了一个(非常)基本准系统 plunker here ,以展示我的方法。我使用moment.js来处理日期,因为我对vanilla javascript日期操作非常糟糕,并且发现它非常笨拙。
这是模板:
<div class="controls">
<button ng-click="prevMonth()"><-</button>
<span>{{selected.format('MMMM')}}</span>
<button ng-click="nextMonth()">-></button>
</div>
<div class="month">
<span class="day" ng-repeat="day in selected.days">
{{day.number}}
</span>
</div>
模板依赖于具有selected
属性的范围,该属性是一个时刻对象。它所做的只是创建一些按钮来更改月份并在顶部显示月份名称,然后为该月的每一天创建一个跨度。
一小部分CSS将日期分为7行:
span.day{
float: left;
width: 25px;
}
span.day:nth-child(7n+1){
clear:left;
}
这是指令的link
功能:
link: function(scope, element, attributes){
// Set the selection to now initially.
scope.selected = moment();
generateDaysArray = function(){
// -- REMOVED FOR BREVITY -- //
return days;
}
// Watch the month for changes and update the days array
scope.$watch(
function(){
return scope.selected.month();
},
function(newVal, oldVal){
scope.selected.days = generateDaysArray();
}
)
// Control button actions
scope.nextMonth = function(){
scope.selected.add('month', 1)
}
scope.prevMonth = function(){
scope.selected.subtract('month', 1)
}
}
确实没有什么特别之处,但请注意所使用的$watch
命令利用了你可以传递一个函数而不是一个字符串的事实(尽管现在你可以使用{{1作为一个字符串)。
如果你想将日期与一周中的几天对齐,那么生成days数组会稍微复杂一些,这是我开始做的,但还没有完成。我的计划是让数组中的每个对象都有一个'selected.month()'
属性,它会使用isPreviousMonth
有条件地应用不同的样式,并且会查找正确的数字,而不是只使用{{1对于偏移天!
要完成此任务还有很多工作要做 - 尤其是使日期可选并与ng-class
集成,但希望这个例子让您了解一种解决模板问题的方法。还有很多其他方法可以做到这一点,但我发现这是最直观的。
扩展程序
要解决有关有多个月的问题,我已经稍微扩展了the plunker。
我在指令中添加了一个属性:
~
根据您在属性中指定的月数,将模板修改为ngModel
个特定部分:
<date-picker num-months="3"></date-picker>
所以这需要一个月的数组,每个月都有2个属性:片刻和天数。我添加了一些快速而又脏的javascript来生成它,但是我不会把它粘贴在这里,因为几乎可以有更简洁的方法来做到这一点!
请注意,目前我们仍在观看ng-repeat
月份的更改,这会导致(可能不需要的)行为,如果您选择的日期不是在第一个月,则日历会重新安排自己。我认为在这种情况下我不会使用<div class="controls">
<button ng-click="prevMonth()"><-</button>
<span ng-repeat="month in months" class="month-title">
{{month.moment.format('MMMM')}}
</span>
<button ng-click="nextMonth()">-></button>
</div>
<div class="month" ng-repeat="month in months">
<span class="day" ng-repeat="day in month.days">
{{day.number}}
</span>
</div>
,而只是添加点击事件来处理正确重新绘制日历。
PS 这解决了克隆部分,但没有解决滚动部分。对于滚动,我建议在month数组的任一端添加一个月,然后具有scope.selected
条件,这意味着只显示中间月份。然后,您可以利用角度内置的动画(this is a good reference)来使用css滚动/滚动它们。如果您想了解更多信息,请通过我为此问题打开的聊天与我联系。