AngularJs:如何将我的部分数据从一个组件传递到另一个组件

时间:2017-05-28 20:20:08

标签: angularjs angularjs-components

我有一个角度控件,用于显示一组数据,大致类似于以下示例。除了一个独特的块,它有许多相同结构的重复(但离散)块。

{
  "person": {
    "lastName": "Bettertester",
    "firstName": "Fester",
    "address": "Out in the woods 17",
    "zipCode": "10666",
    "place": "Back of beyond"
  },
  "contact1": {
    "firstName": "Jane",
    "lastName": "Doe",
    "phone": "555-987-654",
    "relationship": "Aunt"
  },
  "contact2": {
    "firstName": "Kherumple",
    "lastName": "Whaduffle",
    "phone": "555-666-000",
    "relationship": "Imaginary friend"
  },
  "contact3": {
    "firstName": "Kherumple",
    "lastName": "Whaduffle",
    "phone": "555-666-000",
    "relationship": "Imaginary friend"
  }
}

我已经编写了一个angularjs组件来检索和显示这个结构,但是想把重复块移到另一个组件上。

angular.module('myModule').component('mainComponent', {
  templateUrl : 'person.template.html',
  controller : [ '$scope', '$http', function mainController($scope, $http) {
    var self = this;
    self.data = null;
    $http.get(url).then(function(response) {
      self.data = response.data;
    }, function(response, status) {
      console.warn("Error while loading data");
      console.warn(" - response=", response);
      console.warn(" - status=", status);
      self.data = null;
    });
  } ]
});

相应的模板:

<div>
  <h1>Person information</h1>
  <table>
  <tr>
    <th class="label-column">First & last name</th>
    <td class="data">{{$ctrl.data.person.firstName}} {{$ctrl.data.person.lastName}}</td>
  </tr>
  <tr>
    <th class="label-column">Address</th>
    <td class="data">{{$ctrl.data.person.address}}</td>
  </tr>
  <tr>
    <th class="label-column">ZIP code & Place</th>
    <td class="data">{{$ctrl.data.person.zipCode}} {{$ctrl.data.person.place}}</td>
  </tr>
  </table>

  <contact details="{{$ctrl.data.contact1}}"></contact> <!-- passing the details like this sort of works -->
  <contact details="{{$ctrl.data.contact2}}"></contact>
  <contact details="$ctrl.data.contact3"></contact>     <!-- passing the details like this does not work at all -->
</div>

联系方式的控制器如下所示:

angular.module('myModule').component('contact', {
  templateUrl : 'contact.template.html',
  bindings : {
    details : '@'
  },
  controller : [ '$scope', '$http', function contactController($scope, $http) {
    var self = this;
    console.log("- details=", self.details);
  } ]
});

以及相应的模板:

<div>
  <h2>Contact</h2>
  <table>
  <!-- this works -->
  <tr>
    <th class="label-column">Everything</th>
    <td class="data">{{$ctrl.details}}</td>
  </tr>
  <tr>
    <th class="label-column">First & last name</th>
    <td class="data">{{$ctrl.details.firstName}} {{$ctrl.details.lastName}}</td>
  </tr>
  <tr>
    <th class="label-column">Phone</th>
    <td class="data">{{$ctrl.details.phone}}</td>
  </tr>
  <tr>
    <th class="label-column">Relationship</th>
    <td class="data">{{$ctrl.details.relationship}}</td>
  </tr>
  </table>

  <contact details="{{$ctrl.data.contact1}}"></contact>
  <contact details="{{$ctrl.data.contact2}}"></contact>
  <contact details="{{$ctrl.data.contact3}}"></contact>
  <contact details="{{$ctrl.data.contact4}}"></contact>
</div>

我的问题是如何正确地将属于mainComponent的联系人详细信息传递给contactComponent,以便我可以访问相应模板中的字段。如果我在没有花括号的情况下传递它们,则联系人组件似乎根本不会获得任何数据。如果我用花括号传递它们,联系人组件似乎以某种方式获取它们,但不是正确的json对象,因为我无法访问联系人块中的字段。我确定我错过了一些微不足道的东西,却没有找到我出错的地方。

3 个答案:

答案 0 :(得分:1)

  1. 使用单向<绑定而不是插值@绑定 因为@监视插值,如果没有插值,只需将原始属性字符串作为值本身传递。 <=绑定监视表达式更改并相应地使用表达式值更新模板。在这种特殊情况下,<=更方便,因为我们只需要观察组件的输入更改,我们不需要通过更改相同的表达式来影响后端的额外监视。

  2. 使用<使用属性值后,无需安全花括号。

  3. $onInit控制器生命周期钩子中初始化组件逻辑,因为在绑定初始化之后调用此钩子,这正是console.log("- details=", this.details);给出{{1}的原因的确切原因在- details=undefined控制器中。

  4. 代码明细:

    contact
    let app = angular.module('app', []);
    
    app.component('mainComponent', {
      template: `
      <div>
      <h1>Person information</h1>
      <table>
      <tr>
        <th class="label-column">First & last name</th>
        <td class="data">{{$ctrl.data.person.firstName}} {{$ctrl.data.person.lastName}}</td>
      </tr>
      <tr>
        <th class="label-column">Address</th>
        <td class="data">{{$ctrl.data.person.address}}</td>
      </tr>
      <tr>
        <th class="label-column">ZIP code & Place</th>
        <td class="data">{{$ctrl.data.person.zipCode}} {{$ctrl.data.person.place}}</td>
      </tr>
      </table>
    
      <contact details="$ctrl.data.contact1"></contact> <!-- passing the details like this sort of works -->
      <contact details="$ctrl.data.contact2"></contact>
      <contact details="$ctrl.data.contact3"></contact>     <!-- passing the details like this does not work at all -->
    </div>
      `,
      controller: ['$scope', '$http', function mainController($scope, $http) {
      
        var self = this;
        
        self.$onInit = () => {
          self.data = {
            "person": {
              "lastName": "Bettertester",
              "firstName": "Fester",
              "address": "Out in the woods 17",
              "zipCode": "10666",
              "place": "Back of beyond"
            },
            "contact1": {
              "firstName": "Jane",
              "lastName": "Doe",
              "phone": "555-987-654",
              "relationship": "Aunt"
            },
            "contact2": {
              "firstName": "Kherumple",
              "lastName": "Whaduffle",
              "phone": "555-666-000",
              "relationship": "Imaginary friend"
            },
            "contact3": {
              "firstName": "Kherumple",
              "lastName": "Whaduffle",
              "phone": "555-666-000",
              "relationship": "Imaginary friend"
            }
          };
        };
        
      }]
    });
    
    app.component('contact', {
      template: `
        <div>
      <h2>Contact</h2>
      <table>
      <!-- this works -->
      <tr>
        <th class="label-column">Everything</th>
        <td class="data">{{$ctrl.details}}</td>
      </tr>
      <tr>
        <th class="label-column">First & last name</th>
        <td class="data">{{$ctrl.details.firstName}} {{$ctrl.details.lastName}}</td>
      </tr>
      <tr>
        <th class="label-column">Phone</th>
        <td class="data">{{$ctrl.details.phone}}</td>
      </tr>
      <tr>
        <th class="label-column">Relationship</th>
        <td class="data">{{$ctrl.details.relationship}}</td>
      </tr>
      </table>
    </div>
      `,
      bindings: {
        details: '<'
      },
      controller: ['$scope', '$http', function jassMonitorHandController($scope, $http) {
        this.$onInit = () => {
          console.log("- details=", this.details);
        };
      }]
    });

答案 1 :(得分:1)

问题在于details组件中的contact绑定。

它应该是details: '<'(单向绑定)而不是details: '@'(一次字符串绑定)。使用此类绑定时,模板中不需要花括号。

答案 2 :(得分:0)

我认为您可以重写组件以接收联系人数组并使用ng-repeat指令

<div ng-repeat='item in contactList'>
  <table>//your stuff</table>

使用等于运算符的绑定传递数据以接收ng-model

bindings: '='

我可以建议的最后一件事是创建一个服务来检索和存储数据并注入相应的组件

有用资源