【问题标题】:How to run function in a sibling component using AngularJS?如何使用 AngularJS 在兄弟组件中运行函数?
【发布时间】:2017-09-22 16:04:52
【问题描述】:

我需要单击一个控制器中的一个按钮,并让它使用 AngularJS 在同级控制器中触发/运行一个函数。

在我的(非常简化的)示例中,我有一个标题组件和一个内容组件。我有两个按钮可以更改对象的颜色(但是,我的实际情况要复杂得多)。我需要能够从另一个组件调用这些相同的函数。

Here is the Plunker example

INDEX.HTML

<!DOCTYPE html>
<html ng-app="app">

  <head>
    <script src="https://opensource.keycdn.com/angularjs/1.5.8/angular.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.css" />
    <link rel="stylesheet" href="style.css" />

    <script id="header-template" type="text/ng-template">
      <h1>HEADER</h1>
      <button type="button" ng-click="model.makeRed()">Make Red</button>
      <button type="button" ng-click="model.makeBlue()">Make Blue</button>
      <br />
      <br />
      <pre>{{model}}</pre>
      <hr />
    </script>

    <script id="content-template" type="text/ng-template">
      <h2>Content</h2>
      <div ng-class="model.colorme">Object to color</div>
      <br />
      <button type="button" ng-click="model.makeRed()">Make Red</button>
      <button type="button" ng-click="model.makeBlue()">Make Blue</button>
      <br />
      <br />
      <pre>{{model}}</pre>
    </script>

    <script src="script.js"></script>
  </head>

  <body>
    <div class="container">
      <header-component></header-component>
      <content-component></content-component>
    </div>
  </body>

</html>

SCRIPT.JS

console.clear();

function headerController() {
  var model = this; 
  model.test = "test header";

  console.log(model);
}

function contentController() {
  var model = this;
  model.test = "test content";

  model.makeRed = function() {
    model.colorme = "red";
  }

  model.makeBlue = function() {
    model.colorme = "blue";
  }
  console.log(model);
}


var app = angular.module("app", []);

app.component("headerComponent", {
    template: $("#header-template").html(),
    controllerAs: "model",
    controller: [headerController]
});

app.component("contentComponent", {
    template: $("#content-template").html(),
    controllerAs: "model",
    controller: [contentController]
});

STYLE.CSS

.blue { background-color: blue; color: white; }

.red { background-color: red; color: white; }

【问题讨论】:

  • 你试过类似this的东西吗?
  • 我使用组件和那些只是直接的控制器有关系吗?另外,我认为会有某种绑定方法而不是使用 $rootscope (我看到人们有时会推荐它)。
  • 你有这两个组件的父组件吗?
  • @RichC :是的,它应该可以解决问题。可以使用angularjs组件绑定来共享函数或变量(使用= 绑定)
  • @RichC : 当然,我现在就去做

标签: javascript angularjs


【解决方案1】:

以下是跨组件共享数据或功能的 3 种方法:

坏的:

使用&lt;= 绑定在组件之间共享功能是可能的,但非常难看,应该避免。

这是一个例子:

HTML

<script id="header-template" type="text/ng-template">
  <h1>HEADER</h1>
  <button type="button" ng-click="model.selectAll()" class="btn btn-sm btn-default">Select All</button>
  <button type="button" ng-click="model.deselectAll()" class="btn btn-sm btn-default">Deselect All</button>
  <br />
  <br />
  <hr />
</script>

<script id="content-template" type="text/ng-template">
  <h2>Content</h2>
  <button type="button" ng-click="model.selectAll()" class="btn btn-sm btn-default">Select All</button>
  <button type="button" ng-click="model.deselectAll()" class="btn btn-sm btn-default">Deselect All</button>
  <br />
  <br />
  <div class="item_container" multiple-selection-zone>
      <div ng-repeat="f in model.transaction.fields" multiple-selection-item class="well" ng-class="{'selecting': isSelecting ,'selected': isSelected || model.isSelected}">{{f.label}}</div>
  </div>
  <br />
  <br />
</script>

JS

function parentController(TransactionFactory) { 
  var model = this; 
  model.transaction = TransactionFactory;
  model.selectAll = null;
  model.deselectAll = null;
}

function headerController(TransactionFactory) {
  var model = this; 
  model.transaction = TransactionFactory;
}

function contentController(TransactionFactory) {
  var model = this;
  model.transaction = TransactionFactory;

  model.selectAll = function() {
    //mark all fields as selected
    model.isSelected = true;
  }

  model.deselectAll = function() {
    //deselect all fields that are selected
    model.isSelected = false;
  }

  this.$onInit = function() {
    model.cSelectAll = model.selectAll;
    model.cDeselectAll = model.deselectAll;
  }
}


var app = angular.module("app", ['multipleSelection']);

app.factory('TransactionFactory', function () {
    var transaction = {
        fields: [
          {label: "field 1"}, 
          {label: "field 2"}, 
          {label: "field 3"}, 
          {label: "field 4"}, 
          {label: "field 5"}]
    };
    return transaction;
});

app.component("parentComponent", {
    template: $("#parent-template").html(),
    controllerAs: "model",
    controller: ["TransactionFactory", parentController]
});

app.component("headerComponent", {
    template: $("#header-template").html(),
    controllerAs: "model",
    controller: ["TransactionFactory", headerController],
    bindings: {
      selectAll: '<',
      deselectAll: '<',
    }
});

app.component("contentComponent", {
    template: $("#content-template").html(),
    controllerAs: "model",
    controller: ["TransactionFactory", contentController],
    bindings: {
      cSelectAll: '=',
      cDeselectAll: '=',
    }
});

plunker

正确的

HTML

<!DOCTYPE html>
<html ng-app="app">

  <head>
    <script src="https://opensource.keycdn.com/angularjs/1.5.8/angular.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.css" />
    <link rel="stylesheet" href="style.css" />

    <script id="header-template" type="text/ng-template">
      <h1>HEADER</h1>
      <button type="button" ng-click="model.makeRed()">Make Red</button>
      <button type="button" ng-click="model.makeBlue()">Make Blue</button>
      <br />
      <br />
      <pre>{{model}}</pre>
      <hr />
    </script>

    <script id="content-template" type="text/ng-template">
      <h2>Content</h2>
      <div ng-class="model.colorMe">Object to color</div>
      <br />
      <br />
      <br />
      <pre>{{model}}</pre>
    </script>

    <script id="root-template" type="text/ng-template">
      <header-component color-me="model.colorme" make-red="model.makeRed()" make-blue="model.makeBlue()"></header-component>
      <content-component color-me="model.colorme" make-red="model.makeRed()" make-blue="model.makeBlue()"></content-component>
    </script>

    <script src="script.js"></script>
  </head>

  <body>
    <div class="container">
      <root-component></root-component>
    </div>
  </body>

</html>

JS

console.clear();

function headerController() {
  var model = this;
  model.test = "test header";

  console.log(model);
}

function contentController() {
  var model = this;
  model.test = "test content";
  model.makeBlue();
  console.log(model);
}

function rootController() {
  var model = this;

  model.makeRed = function() {
    console.log('red');
    model.colorme = "red";
  }

  model.makeBlue = function() {
    console.log('blue');
    model.colorme = "blue";
  }
  console.log(model);
}


var app = angular.module("app", []);

app.component("rootComponent", {
  template: $("#root-template").html(),
  controllerAs: "model",
  controller: [rootController]
});

app.component("headerComponent", {
  template: $("#header-template").html(),
  controllerAs: "model",
  controller: [headerController],
  bindings: {
    makeRed: '&',
    makeBlue: '&',
    colorMe: '<',
  }
});

app.component("contentComponent", {
  template: $("#content-template").html(),
  controllerAs: "model",
  controller: [contentController],
  bindings: {
    makeRed: '&',
    makeBlue: '&',
    colorMe: '<',
  }
});

你的plunker

通过绑定,您可以将变量 (colorMe) 与 &lt; 绑定或函数(makeBlue 和 makeRed)与 &amp; 绑定在具有相同父级的组件之间共享。

完美的一个

您可以使用 angular.service 来存储和修改状态并在组件之间共享。

【讨论】:

  • 该死 - 我认为我必须在 contentComponent 中拥有这些功能,因为我必须在该组件中做一些复杂的工作。这不是将属性从蓝色变为红色那么简单。
  • 我会在几个小时内告诉你。我们可以使用经典绑定(
  • 太棒了,谢谢!在此期间,我会看看我是否可以自己解决。
  • 哇——这玩意儿让我头疼。无法弄清楚,但我在这个 plunker 中做了更接近我的场景:plnkr.co/edit/IoezfScfM43XMeqvpon6?p=preview
  • @RichC :我更新了您的新 plnkr(和答案):plnkr.co/edit/UTVO5vSMYrDktcVhjh1p?p=preview 使用与您的情况相匹配的丑陋解决方案。但是您绝对应该使用服务来执行这样的想法。明天将在答案中提供服务示例:)
猜你喜欢
  • 1970-01-01
  • 2017-11-11
  • 1970-01-01
  • 1970-01-01
  • 2022-01-14
  • 1970-01-01
  • 2016-12-03
  • 1970-01-01
  • 2018-10-28
相关资源
最近更新 更多