web-dev-qa-db-ja.com

でコントロール間でデータを渡す Angular JS?

私の製品を表示する基本的なコントローラがあります。

App.controller('ProductCtrl',function($scope,$productFactory){
     $productFactory.get().success(function(data){
           $scope.products = data;
     });
});

私の見解では、私はリストにこの商品を表示しています

<ul>
    <li ng-repeat="product as products">
        {{product.name}}
    </li>
</ul

私がやろうとしているのは、誰かが製品名をクリックしたとき、私はこの製品が追加されているカートという名前の別のビューがあります。

 <ul class="cart">
      <li>
          //click one added here
      </li>
      <li>
          //click two added here
      </li>
 </ul>

それで、ここで私が疑問に思うのは、このクリックされた製品を最初のコントローラーから2番目のコントローラーにどのように渡すかということです。私はカートもコントローラであるべきだと思いました。

Clickイベントはディレクティブを使って処理します。また、上記の機能を実現するにはサービスを使用する必要があると思いますカートは事前に定義された商品数になるので、どのページのユーザーであるかによって5/10になる可能性があります。だから私はこれを一般的なものにしておきたい。

更新:

私はブロードキャストするためのサービスを作成し、2番目のコントローラで私はそれを受信します。今クエリはどのように私はDOMを更新するのですか?製品をドロップする私のリストはかなりハードコーディングされているので。

235
kishanio

説明から、まるでサービスを使うべきかのようです。いくつかの例を見るには、 http://egghead.io/lessons/angularjs-sharing-data-between-controllers および AngularJSサービスがデータを渡す を確認してください。

製品サービスを(工場として)次のように定義できます。

app.factory('productService', function() {
  var productList = [];

  var addProduct = function(newObj) {
      productList.Push(newObj);
  };

  var getProducts = function(){
      return productList;
  };

  return {
    addProduct: addProduct,
    getProducts: getProducts
  };

});

依存関係はサービスを両方のコントローラに注入します。

ProductControllerで、選択したオブジェクトを配列に追加するアクションをいくつか定義します。

app.controller('ProductController', function($scope, productService) {
    $scope.callToAddToProductList = function(currObj){
        productService.addProduct(currObj);
    };
});

あなたのCartControllerで、サービスから製品を入手してください:

app.controller('CartController', function($scope, productService) {
    $scope.products = productService.getProducts();
});
317
Chalise

このクリックされた商品を最初のコントローラーから2番目にどのように渡しますか?

クリックすると、 broadcast を呼び出すメソッドを呼び出すことができます。

$rootScope.$broadcast('SOME_TAG', 'your value');

そして2番目のコントローラはこのタグをリッスンします。

$scope.$on('SOME_TAG', function(response) {
      // ....
})

$ scopeをサービスに注入することはできないので、シングルトン$ scopeのようなものは何もありません。

しかし$rootScopeを注入することができます。そのため、サービスに値を格納すると、サービス本体で$rootScope.$broadcast('SOME_TAG', 'your value');を実行できます。 (サービスに関する@Charxの説明を参照)

app.service('productService',  function($rootScope) {/*....*/}

$ broadcast$ emit についての良い記事をチェックしてください。

66
Maxim Shoustin

Serviceを作成せずに$ rootScopeを使用して解決する:

アプリコントローラ間でプロパティを共有するには、Angular $ rootScopeを使用できます。これはデータを共有するもう1つの方法で、人々がそれを知ることができるようにします。

いくつかの機能をコントローラ間で共有するための推奨される方法は、サービスです。$ rootscopeを使用してグローバルプロパティを読み取りまたは変更することができます。

var app = angular.module('mymodule',[]);
app.controller('Ctrl1', ['$scope','$rootScope',
  function($scope, $rootScope) {
    $rootScope.showBanner = true;
}]);

app.controller('Ctrl2', ['$scope','$rootScope',
  function($scope, $rootScope) {
    $rootScope.showBanner = false;
}]);

テンプレートで$ rootScopeを使用する($ rootでプロパティにアクセスする):

<div ng-controller="Ctrl1">
    <div class="banner" ng-show="$root.showBanner"> </div>
</div>
24
Sanjeev

これには2つの方法があります。

  1. $rootscopeを使用することによって、しかし私はこれを推薦しません。 $rootScopeは最上位のスコープです。アプリは、アプリのすべてのコンポーネント間で共有される$rootScopeを1つだけ持つことができます。したがって、それはグローバル変数のように振る舞います。

  2. サービスを利用するこれを行うには、2つのコントローラ間でサービスを共有します。サービス用のコードは次のようになります。

    app.service('shareDataService', function() {
        var myList = [];
    
        var addList = function(newObj) {
            myList.Push(newObj);
        }
    
        var getList = function(){
            return myList;
        }
    
        return {
            addList: addList,
            getList: getList
        };
    });
    

    あなたは私のフィドル ここ を見ることができます。

16
Nisham Mahsin

コントローラ間でデータを共有するさらに簡単な方法は、ネストしたデータ構造を使用することです。代わりに、例えば

$scope.customer = {};

使用できます

$scope.data = { customer: {} };

dataプロパティは親のスコープから継承されるので、他のコントローラからのアクセスを維持しながらフィールドを上書きすることができます。

9
Barth Zalewski
angular.module('testAppControllers', [])
    .controller('ctrlOne', function ($scope) {
        $scope.$broadcast('test');
    })
    .controller('ctrlTwo', function ($scope) {
        $scope.$on('test', function() {
        });
    });
8
Jijo Paulose

セッション内のデータを保存することができ、アウトプログラムのどこでもそれを使用することができます。

$window.sessionStorage.setItem("Mydata",data);

別の場所

$scope.data = $window.sessionStorage.getItem("Mydata");
5
Alex Kumbhani

私はここで答えを見ました、そしてそれはコントローラ間でデータを共有するという質問に答えています、しかし私がデータが変更されたという事実について他のコントローラに通知したいならどうしますか?簡単!有名な訪問者パターンを使用するだけです。

myApp.service('myService', function() {

    var visitors = [];

    var registerVisitor = function (visitor) {
        visitors.Push(visitor);
    }

    var notifyAll = function() {
        for (var index = 0; index < visitors.length; ++index)
            visitors[index].visit();
    }

    var myData = ["some", "list", "of", "data"];

    var setData = function (newData) {
        myData = newData;
        notifyAll();
    }

    var getData = function () {
        return myData;
    }

    return {
        registerVisitor: registerVisitor,
        setData: setData,
        getData: getData
    };
}

myApp.controller('firstController', ['$scope', 'myService',
    function firstController($scope, myService) {

        var setData = function (data) {
            myService.setData(data);
        }

    }
]);

myApp.controller('secondController', ['$scope', 'myService',
    function secondController($scope, myService) {

        myService.registerVisitor(this);

        this.visit = function () {
            $scope.data = myService.getData();
        }

        $scope.data = myService.getData();
    }
]);

この簡単なやり方で、あるコントローラは、いくつかのデータが更新されたことを他のコントローラに更新することができる。

4
Omri Lahav

ルートパスのパターン間で共有範囲を制御するファクトリを作成したので、ユーザーが同じルートの親パスで移動しているときにも共有データを維持できます。

.controller('CadastroController', ['$scope', 'RouteSharedScope',
    function($scope, routeSharedScope) {
      var customerScope = routeSharedScope.scopeFor('/Customer');
      //var indexScope = routeSharedScope.scopeFor('/');
    }
 ])

そのため、ユーザーが別のルートパス、たとえば '/ Support'に移動すると、パス '/ Customer'の共有データは自動的に破棄されます。しかし、これの代わりにユーザーが「/ Customer/1」や「/ Customer/list」のように「子」パスに移動しても、スコープは破棄されません。

あなたはここでサンプルを見ることができます: http://plnkr.co/edit/OL8of9

3
Oberdan Nunes

誰かに役立つかどうかはわかりませんが、Charx(ありがとう)の回答に基づいて、単純なキャッシュサービスを作成しました。気軽に使用、リミックス、共有してください。

angular.service('cache', function() {
    var _cache, _store, _get, _set, _clear;
    _cache = {};

    _store = function(data) {
        angular.merge(_cache, data);
    };

    _set = function(data) {
        _cache = angular.extend({}, data);
    };

    _get = function(key) {
        if(key == null) {
            return _cache;
        } else {
            return _cache[key];
        }
    };

    _clear = function() {
        _cache = {};
    };

    return {
        get: _get,
        set: _set,
        store: _store,
        clear: _clear
    };
});
2
marverix

角度サービスを使用する1つの方法:

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

app.controller('one', function($scope, ser1){
$scope.inputText = ser1;
});


app.controller('two',function($scope, ser1){
$scope.inputTextTwo = ser1;
});

app.factory('ser1', function(){
return {o: ''};
});



<div ng-app='home'>

<div ng-controller='one'>
  Type in text: 
  <input type='text' ng-model="inputText.o"/>
</div>
<br />

<div ng-controller='two'>
  Type in text:
  <input type='text' ng-model="inputTextTwo.o"/>
</div>

</div>

https://jsfiddle.net/1w64222q/

2
Siva ganesh

モジュールにファクトリを作成し、そのファクトリの参照をコントローラに追加し、その変数をコントローラで使用して、必要に応じて参照を追加することによって別のコントローラのデータの値を取得する

2
Resham Kadel

1

using $localStorage

app.controller('ProductController', function($scope, $localStorage) {
    $scope.setSelectedProduct = function(selectedObj){
        $localStorage.selectedObj= selectedObj;
    };
});

app.controller('CartController', function($scope,$localStorage) { 
    $scope.selectedProducts = $localStorage.selectedObj;
    $localStorage.$reset();//to remove
});

2

クリックすると、ブロードキャストを呼び出すメソッドを呼び出すことができます。

$rootScope.$broadcast('SOME_TAG', 'your value');

and the second controller will listen on this tag like:
$scope.$on('SOME_TAG', function(response) {
      // ....
})

3

using $rootScope:

4

window.sessionStorage.setItem("Mydata",data);
$scope.data = $window.sessionStorage.getItem("Mydata");

5

角度サービスを使用する1つの方法:

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

app.controller('one', function($scope, ser1){
$scope.inputText = ser1;
});

app.controller('two',function($scope, ser1){
$scope.inputTextTwo = ser1;
});

app.factory('ser1', function(){
return {o: ''};
});
2
Subhransu

$ broadcastを使用して@Maximによって提案されたソリューションを改善するために、送信データは変更されません

$rootScope.$broadcast('SOME_TAG', 'my variable');

しかしデータを聞くこと

$scope.$on('SOME_TAG', function(event, args) {
    console.log("My variable is", args);// args is value of your variable
})
1
Cedriga

FYI $ scopeオブジェクトは$ emit、$ broadcast、$ onを持ち、$ rootScopeオブジェクトは同一の$ emit、$ broadcast、$ onを持ちます

デザインパターンのパブリッシュ/サブスクライブについてもっと詳しく ここ

1

それには3つの方法があります。

a)サービスを利用する

b)コントローラスコープ間の依存する親子関係を利用する。

c)In Angular 2.0 "As"キーワードは、あるコントローラから別のコントローラにデータを渡します。

例で詳細については、以下のリンクを確認してください。

http://www.tutespace.com/2016/03/angular-js.html

var custApp = angular.module("custApp", [])
.controller('FirstController', FirstController)
.controller('SecondController',SecondController)
.service('sharedData', SharedData);

FirstController.$inject = ['sharedData'];
function FirstController(sharedData) {
this.data = sharedData.data;
}

SecondController.$inject['sharedData'];
function SecondController(sharedData) {
this.data = sharedData.data;
}

function SharedData() {
this.data = {
    value: 'default Value'
}
}

最初のコントローラー

<div ng-controller="FirstController as vm">
<input type=text ng-model="vm.data.value" />
</div>

セカンドコントローラー

 <div ng-controller="SecondController as vm">
    Second Controller<br>
    {{vm.data.value}}
</div>
0
testmeon