我正在使用修改DOM的指令,因此必须在调用所有postLink fns之后完成。 (see angular-ui modules/directives/select2/select2.js:103)
鉴于某些先决条件(未在URL中编码),我想将焦点设置为页面上的第一个select2元素。这是有问题的,因为在设置焦点之前,必须初始化select2,并且没有一些俗气的任意延迟> 0,我无法安排广播的事件来设置焦点。
我创建了以下指令,该指令将侦听焦点primaryInput / focus事件并设置焦点。
# TODO - should we create a directive for tab order instead?
app.directive "primaryInput", () ->
{
name: "primaryInput"
link: (scope, element, attrs) ->
scope.$on "primaryInput/focus", ->
element.focus()
}
更改primaryInput指令优先级不起作用,因为任何优先级将在调度setTimeout函数之前运行。
理想情况下,我希望能够拥有一个promises集合,每个promise将每个延迟指令推送到一个堆栈,然后一个promise将在所有这些promise完成后得到解决。我会把我的问题集中在如何最好地实现这个目标上,但我已经想到了一种不太好的方法,想要探索更好的方法,并且想要避免使用XY problem。
谢谢!
在完成这里描述问题的努力后退了一步,我想到了一个可接受的方法解决我的问题,并会回答我自己的问题,但如果有人有更好的方法,请保持开放。
答案 0 :(得分:1)
由于延迟执行复杂性在处理Select2的指令中,我现在决定将那种复杂性隔离开来。
我覆盖了Select2指令中元素的焦点函数,因此焦点调用一旦可用就转发到select2实例。这样,可以告诉元素在select2之前聚焦。
我的焦点指示:
app.directive "input", ($injector) ->
primaryMatcher = (e,attrs) ->
attrs.primary?
{
name: "inputFocus"
restrict: 'E'
link: (scope, element, attrs) ->
scope.$on "focus", (e, matcher)->
if ((matcher || primaryMatcher)(element, attrs))
console.log("focus", element, attrs)
element.focus()
}
在我的Select2指令中:
app.directive "s2Factor", () ->
# ...
{
name: "s2Factor"
require: "?ngModel"
priority: 1
restrict: "A"
link: (scope, el, attr, controller) ->
select2_p = $.Deferred()
# ...
setTimeout ->
el.select2 opts
select2_p.resolve(el.data("select2"))
el.focus = () ->
select2_p.then (select2) ->
select2.focus()
}
它涉及实例猴子修补,但我发现在这种情况下它是可以接受的。