繁体   English   中英

如何使用来自两个不同组件中引用的服务的数据填充工厂?

[英]How to populate factory with data from service referenced in two different components?

我正在尝试找出一种在两个不同组件中使用数据服务填充工厂的方法。 在没有数据服务的情况下,工厂可以在两个组件之间很好地同步,但是一旦我添加了它,工厂就会在两个组件之间停止同步。

这是示例的Plunker。 script.js文件中注释掉的代码是我尝试实现数据服务的两个地方,但是这破坏了这两个地方的工厂同步。 (您可以使用“添加”按钮进行测试)

index.html

<!DOCTYPE html>
<html>

<head>
  <link rel="stylesheet" href="//kendo.cdn.telerik.com/2017.1.118/styles/kendo.common.min.css" />
  <link rel="stylesheet" href="//kendo.cdn.telerik.com/2017.1.118/styles/kendo.bootstrap.min.css" />
  <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.css" />


  <script src="//code.jquery.com/jquery-1.12.4.js"></script>
  <script src="//code.angularjs.org/1.5.8/angular.js"></script>
  <script src="//kendo.cdn.telerik.com/2017.1.118/js/kendo.all.min.js"></script>
  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular-animate.js"></script>
  <script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/2.5.0/ui-bootstrap-tpls.js"></script>

  <script id="documents1-template" type="text/ng-template">
    <button class="btn btn-default" ng-click="model.addDoc()">Add Document</button>
    <pre>{{ model | json }}</pre>
  </script>

  <script id="documents2-template" type="text/ng-template">
    <button class="btn btn-default" ng-click="model.addDoc()">Add Document</button>
    <pre>{{ model | json }}</pre>
  </script>

  <link rel="stylesheet" href="style.css" />
  <script src="script.js"></script>
</head>

<body>

<div ng-app="app">

  <div class="row">

    <div class="col-xs-6">
      <documents1-component></documents1-component>
    </div>

    <div class="col-xs-6">
      <documents2-component></documents2-component>
    </div>

  </div>

</div>

</body>

</html>

script.js

console.clear();

function addButton()
{
  var d = {};
  d.id = Math.random().toString().substring(2, 6);
  d.fileName = "Test" + d.id + ".pdf";
  return d;
}

function documents1Controller($uibModal, DataService, TransactionFactory) {
  var model = this;

  model.transaction = TransactionFactory;

  //model.transaction = DataService.getTransactionDetails().then(function (result) {
  //                  model.transaction = result.data.transaction;
  //              }, function (reason) {
  //                  alert('Failed: ' + reason);
  //                  model.transaction = TransactionFactory;
  //              });


  model.addDoc = function(){
    var newDoc = addButton();
    model.transaction.documents.push(newDoc);
  }
}

function documents2Controller($uibModal, DataService, TransactionFactory) {
  var model = this;
  model.transaction = TransactionFactory;

  model.addDoc = function(){
    var newDoc = addButton();
    model.transaction.documents.push(newDoc);
  }
}

var app = angular.module("app", ["kendo.directives", "ngAnimate", "ui.bootstrap"]);

app.factory('TransactionFactory', function(DataService) {

  //return DataService.getTransactionDetails().then(function(results){
  //  console.log(results.data.transaction);
  //  return results.data.transaction;
  //});

  return {
    documents: [],
    participants: []
  }
});

app.component("documents1Component", {
    template: $("#documents1-template").html(),
    controllerAs: "model",
    controller: ["$uibModal", "DataService", "TransactionFactory", documents1Controller]
});

app.component("documents2Component", {
    template: $("#documents2-template").html(),
    controllerAs: "model",
    controller: ["$uibModal", "DataService", "TransactionFactory", documents2Controller]
});

app.service('DataService', ["$http", function ($http) {

    this.getTransactionDetails = function () {
        var getTransactionUrl = "data.json";
        var response = $http.get(getTransactionUrl);
        console.log(response);
        return response;
    };

}]);

data.json

{
  "transaction": {
    "documents": [
      {
        "id": 1,
        "fileName": "fw9.pdf"
      },
      {
        "id": 2,
        "fileName": "Test60pagedoc.pdf"
      },
      {
        "id": 3,
        "fileName": "New Contract Order Form.pdf"
      },
      {
        "id": 4,
        "fileName": "TestForm.pdf"
      },
      {
        "id": 5,
        "fileName": "readyforsignature.pdf"
      }
    ],
    "participants": []
  }
}

在使用简单工厂的第一种情况下,您总是返回完全相同的对象。 这样,如果您从注入了元素的任何组件中将元素添加到数组,它将影响所有其他组件。

// This will always return the same object
  return {
    documents: [],
    participants: [],
    unique: Math.random()// just to prove it, if you print this out it will always be the same number
  }

对于服务,您每次都在创建一个新对象。 即使内容相同,但就解释器而言,它们是完全无关的。

var response = $http.get(getTransactionUrl);// this will always return a new object
    console.log(response);
    return response;

您需要创建一个对象来保持同步状态,并在您进行http调用或在应用程序中对其进行修改时对其进行更新。 我不太确定解决此问题的最佳方法是什么,因为我不了解您的问题域,但是似乎最好将状态保留在服务中,并提供所需的任何CRUD方法来保持同步而不是直接修改全局共享对象。

几件事:

  1. 服务是单例。 “这意味着,进样器使用每个配方最多一次来创建对象,然后将注射器缓存为未来的所有需求参考” 来源 工厂不是。 一个工厂将在两个控制器之间进行数据绑定,而一项服务则不会。

  2. 服务声明的语法有点奇怪。 在这里更正了它以便按照您想要的方式正确使用服务。 DataService.getTransactionDetails()可以单独调用,而无需将其分配给任何对象。

这个故事的寓意是,也许您希望您的工厂使用该服务进行api调用或其他操作。 我不确定,但是服务不能像您尝试的那样工作,因为它们是单例

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM