AngularJS在返回$ http响应后执行链接功能

foo*_*sus 2 angularjs angularjs-directive

我需要在http响应返回后在指令中执行链接功能.这个想法是这样的:

<input type="text" my-field>
<script>
 angular.module("mine")
 .controller ('myCtrl', function ($scope) {
  $http.get("/my/service").success(function (data, status, headers, config) {
    // OK, done with the query... now I know my field name to bind to. Somehow
    // I have to get it down to the link function below...
  });
 })
 .directive ('myField', function ($compile) {
  return {
    link: function (scope, element, attrs) {
      var my_field = attrs.myField;
      element.removeAttr('my-field');

      // Somehow figure out the field here in ngFieldSpec
      element.attr('ng-model', ngFieldSpec);
      $compile(element)(scope);
    };
   });
</script>
Run Code Online (Sandbox Code Playgroud)

在这里,我需要将输入字段绑定到响应的元素,但在得到响应之前,我不知道该元素将被调用.但是当我运行它时,指令的链接在$ http完成之前运行:实际的序列是

  • $ http.get开始
  • 指令的链接功能运行
  • $ http.get返回成功

我对$ q有些熟悉,但我不确定如何用它来完成需要做的事情.顺便说一句,我只显示了一个调用myField指令的输入字段,但页面上可能有很多字段,它们都需要相同的信息.

编辑以响应请求添加更多信息:

我有一个返回JSON数据结构的服务.我事先并不确切知道数据结构会是什么样子,但我可以弄清楚它并将字段与我的页面的输入字段相匹配.我试图在链接功能中进行匹配.我很高兴在其他地方做到这一点; 我可以在$ http.success函数中执行此操作,但这将在控制器中执行DOM操作; 我的理解是DOM操作只能在指令中完成.

这是我的HTML需要的样子:

<input type="text" my-field="[MY_EXTENSION_NAME]myFieldName">
<input type="text" my-field="[MY_EXTENSION_NAME]myFieldName2">
<input type="text" my-field="[MY_EXTENSION_NAME_2]myFieldName">
Run Code Online (Sandbox Code Playgroud)

服务器的响应如下:

{
    realField1: "Diddly",
    realField2: "Squat",
    extensions: [
      {
        name: "MY_EXTENSION_NAME",
        fields: [
          { name="myFieldName" value="Foo" },
          { name="myFieldName2" value="Bar" }
        ]
      },
      {
        name: "MY_EXTENSION_NAME_2",
        fields: [
          { name="myFieldName" value="Baz" },
          { name="myFieldName2" value="Buz" }
        ]
      }
    ]
 }
Run Code Online (Sandbox Code Playgroud)

服务器的响应可能会有所不同,因为:

  • 可能有任意数量的扩展程序("MY_EXTENSION_NAME"等)
  • 可以按任何顺序返回扩展名
  • 可能有任何数量的字段
  • 可以按任何顺序返回字段

这里的整个问题是我想将"[MY_EXTENSION_NAME] myFieldName"转换为ng-model"model.extensions [0] .fields [0] .value.但是,我现在正在考虑在阅读过程中将数据转换为规范形式将更容易,因此ng-model可以只是"model.my_extension_name.myFieldName".

gka*_*pak 5

目前尚不清楚你想要实现的目标(我很确定会有更好的方法),但你可以这样做:

1.
在您的范围内定义承诺:

app.controller('myCtrl', function ($http, $scope) {
    $scope.model = {
        promise: $http.get('/my/service'),
        myField01: 'Hello, world, from 01 !',
        myField02: 'Hello, world, from 02 !',
        myField03: 'Hello, world, form 03 !'
    };
});
Run Code Online (Sandbox Code Playgroud)

2.
从您的HTML中引用该承诺,以便将其传递给您的指令:

<input type="text" my-field="model.promise" />
Run Code Online (Sandbox Code Playgroud)

3.
将此承诺纳入指令的隔离范围:

app.directive ('myField', function ($compile) {
    return {
        scope: { promise: '=myField' },
        ...
Run Code Online (Sandbox Code Playgroud)

4.
在你的link函数中,注册一个回调函数,以便在你的请求得到解决时(即你得到对你的请求的响应)并进行所有必要的操作:

...
link: function (scope, elem, attrs) {
    scope.promise.success(function (data) {
        elem.removeAttr('my-field');
        elem.attr('ng-model', 'model.' + data.fieldName);
        $compile(elem)(scope.$parent);
    });
}
Run Code Online (Sandbox Code Playgroud)

另见这个简短的演示.