0

DOM を変更するディレクティブを使用しているため、すべての postLink fn が呼び出された後に実行する必要があります。( angular-ui modules/directives/select2/select2.js:103 を参照)

特定の前提条件 (URL にエンコードされていない) を考えると、ページの最初の select2 要素にフォーカスを設定したいと思います。フォーカスを設定する前に select2 を初期化する必要があり、安っぽい任意の遅延 > 0 がなければ、フォーカスを設定するイベントをブロードキャストするようにスケジュールできないため、これは問題です。

focus 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()
  }

setTimeout 関数がスケジュールされる前に優先度が実行されるため、primaryInput ディレクティブの優先度を変更しても機能しません。

理想的には、各遅延ディレクティブがスタックにプッシュするプロミスのコレクションを作成し、それらのプロミスがすべて完了すると解決されるプロミスを作成できるようにしたいと考えています。私はこれをどのように達成するのが最善かについて質問を集中させていただろうが、私はすでにあまり良くない方法を考えることができ、より良い方法を探り、 XY問題を避けたい.

ありがとうございました!

アップデート

ここで問題を説明する努力をした後、一歩下がって、私は自分の問題に対する受け入れ可能なアプローチを考え、自分の質問に答えますが、誰かがより良いアプローチを持っている場合は開いたままにしておきます.

4

1 に答える 1

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()
  }

これにはインスタンス モンキー パッチが含まれますが、この場合は許容できると思います。

于 2012-11-06T18:16:55.957 に答える