development

AngularJS 컨트롤러간에 데이터 공유

big-blog 2020. 2. 29. 15:24
반응형

AngularJS 컨트롤러간에 데이터 공유


컨트롤러간에 데이터를 공유하려고합니다. 유스 케이스는 다단계 양식이며 한 입력에 입력 된 데이터는 나중에 원래 컨트롤러 외부의 여러 표시 위치에서 사용됩니다. 아래와 jsfiddle의 코드는 여기에 있습니다 .

HTML

<div ng-controller="FirstCtrl">
    <input type="text" ng-model="FirstName"><!-- Input entered here -->
    <br>Input is : <strong>{{FirstName}}</strong><!-- Successfully updates here -->
</div>

<hr>

<div ng-controller="SecondCtrl">
    Input should also be here: {{FirstName}}<!-- How do I automatically updated it here? -->
</div>

JS

// declare the app with no dependencies
var myApp = angular.module('myApp', []);

// make a factory to share data between controllers
myApp.factory('Data', function(){
    // I know this doesn't work, but what will?
    var FirstName = '';
    return FirstName;
});

// Step 1 Controller
myApp.controller('FirstCtrl', function( $scope, Data ){

});

// Step 2 Controller
myApp.controller('SecondCtrl', function( $scope, Data ){
    $scope.FirstName = Data.FirstName;
});

도움을 주시면 감사하겠습니다.


간단한 해결책은 팩토리가 객체를 반환하고 컨트롤러가 동일한 객체에 대한 참조로 작동하게하는 것입니다.

JS :

// declare the app with no dependencies
var myApp = angular.module('myApp', []);

// Create the factory that share the Fact
myApp.factory('Fact', function(){
  return { Field: '' };
});

// Two controllers sharing an object that has a string in it
myApp.controller('FirstCtrl', function( $scope, Fact ){
  $scope.Alpha = Fact;
});

myApp.controller('SecondCtrl', function( $scope, Fact ){
  $scope.Beta = Fact;
});

HTML :

<div ng-controller="FirstCtrl">
    <input type="text" ng-model="Alpha.Field">
    First {{Alpha.Field}}
</div>

<div ng-controller="SecondCtrl">
<input type="text" ng-model="Beta.Field">
    Second {{Beta.Field}}
</div>

데모 : http://jsfiddle.net/HEdJF/

응용 프로그램이 커지고 테스트가 더 복잡해지고 더 어려워지면 공장에서 전체 객체를 이런 식으로 노출하지 않고 대신 getter 및 setter를 통해 액세스를 제한 할 수 있습니다.

myApp.factory('Data', function () {

    var data = {
        FirstName: ''
    };

    return {
        getFirstName: function () {
            return data.FirstName;
        },
        setFirstName: function (firstName) {
            data.FirstName = firstName;
        }
    };
});

이 접근 방식을 사용하면 새로운 값으로 공장을 업데이트하고 변경 사항을 감시하는 것은 소비 컨트롤러에 달려 있습니다.

myApp.controller('FirstCtrl', function ($scope, Data) {

    $scope.firstName = '';

    $scope.$watch('firstName', function (newValue, oldValue) {
        if (newValue !== oldValue) Data.setFirstName(newValue);
    });
});

myApp.controller('SecondCtrl', function ($scope, Data) {

    $scope.$watch(function () { return Data.getFirstName(); }, function (newValue, oldValue) {
        if (newValue !== oldValue) $scope.firstName = newValue;
    });
});

HTML :

<div ng-controller="FirstCtrl">
  <input type="text" ng-model="firstName">
  <br>Input is : <strong>{{firstName}}</strong>
</div>
<hr>
<div ng-controller="SecondCtrl">
  Input should also be here: {{firstName}}
</div>

데모 : http://jsfiddle.net/27mk1n1o/


나는 $watch이것을 사용하지 않는 것을 선호 합니다. 전체 서비스를 컨트롤러 범위에 할당하는 대신 데이터 만 할당 할 수 있습니다.

JS :

var myApp = angular.module('myApp', []);

myApp.factory('MyService', function(){
  return {
    data: {
      firstName: '',
      lastName: ''
    }
    // Other methods or objects can go here
  };
});

myApp.controller('FirstCtrl', function($scope, MyService){
  $scope.data = MyService.data;
});

myApp.controller('SecondCtrl', function($scope, MyService){
   $scope.data = MyService.data;
});

HTML :

<div ng-controller="FirstCtrl">
  <input type="text" ng-model="data.firstName">
  <br>Input is : <strong>{{data.firstName}}</strong>
</div>
<hr>
<div ng-controller="SecondCtrl">
  Input should also be here: {{data.firstName}}
</div>

또는 직접 방법으로 서비스 데이터를 업데이트 할 수 있습니다.

JS :

// A new factory with an update method
myApp.factory('MyService', function(){
  return {
    data: {
      firstName: '',
      lastName: ''
    },
    update: function(first, last) {
      // Improve this method as needed
      this.data.firstName = first;
      this.data.lastName = last;
    }
  };
});

// Your controller can use the service's update method
myApp.controller('SecondCtrl', function($scope, MyService){
   $scope.data = MyService.data;

   $scope.updateData = function(first, last) {
     MyService.update(first, last);
   }
});

컨트롤러간에 데이터를 공유 할 수있는 많은 방법이 있습니다

  1. 서비스 사용
  2. $ state.go 서비스 사용
  3. stateparams 사용
  4. 루트 스코프 사용

각 방법에 대한 설명 :

  1. 나는 누군가가 이미 설명 한대로 설명하지 않을 것입니다

  2. 사용 $state.go

      $state.go('book.name', {Name: 'XYZ'}); 
    
      // then get parameter out of URL
      $state.params.Name;
    
  3. $stateparam와 비슷한 방식으로 작동하며 $state.go송신자 컨트롤러에서 객체로 객체를 전달하고 stateparam을 사용하여 수신기 컨트롤러에서 수집합니다.

  4. 사용 $rootscope

    (a) 자식 컨트롤러에서 부모 컨트롤러로 데이터 전송

      $scope.Save(Obj,function(data) {
          $scope.$emit('savedata',data); 
          //pass the data as the second parameter
      });
    
      $scope.$on('savedata',function(event,data) {
          //receive the data as second parameter
      }); 
    

    (b) 부모에서 자식 컨트롤러로 데이터 전송

      $scope.SaveDB(Obj,function(data){
          $scope.$broadcast('savedata',data);
      });
    
      $scope.SaveDB(Obj,function(data){`enter code here`
          $rootScope.$broadcast('saveCallback',data);
      });
    

경로 경로 패턴 사이의 공유 범위를 제어하는 ​​팩토리를 만들었으므로 사용자가 동일한 경로 상위 경로를 탐색 할 때만 공유 데이터를 유지할 수 있습니다.

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

따라서 사용자가 다른 경로 경로 (예 : '/ Support')로 이동하면 경로 '/ Customer'에 대한 공유 데이터가 자동으로 삭제됩니다. 그러나이 대신 사용자가 '/ Customer / 1'또는 '/ Customer / list'와 같은 'child'경로로 이동하면 범위가 손상되지 않습니다.

여기에서 샘플을 볼 수 있습니다 : http://plnkr.co/edit/OL8of9


컨트롤러간에 데이터를 공유하는 방법에는 여러 가지가 있습니다

  • 각도 서비스
  • 브로드 캐스트, $ emit 방법
  • 부모-자식 컨트롤러 통신
  • $ rootscope

우리가 알고 있듯이 $rootscope데이터 전송 또는 통신에 바람직하지 않은 방법은 전체 응용 프로그램에서 사용할 수있는 전역 범위이므로

Angular Js 컨트롤러 간의 데이터 공유를 위해 Angular 서비스는 모범 사례입니다. .factory, .service
레퍼런스

아이 컨트롤러에 부모로부터의 데이터 전송의 경우 당신은을 통해 아이 컨트롤러에 직접 액세스 상위 데이터 수 있습니다 $scope
당신이 사용하는 경우 ui-router당신은 사용할 수있는 $stateParmasURL 매개 변수처럼 전달하는 id, name, key, 등

$broadcast컨트롤러간에 데이터를 상위에서 하위 $emit로 전송 하고 하위에서 상위 컨트롤러로 데이터를 전송하는 좋은 방법입니다.

HTML

<div ng-controller="FirstCtrl">
   <input type="text" ng-model="FirstName">
   <br>Input is : <strong>{{FirstName}}</strong>
</div>

<hr>

<div ng-controller="SecondCtrl">
   Input should also be here: {{FirstName}}
</div>

JS

myApp.controller('FirstCtrl', function( $rootScope, Data ){
    $rootScope.$broadcast('myData', {'FirstName': 'Peter'})
});

myApp.controller('SecondCtrl', function( $rootScope, Data ){
    $rootScope.$on('myData', function(event, data) {
       $scope.FirstName = data;
       console.log(data); // Check in console how data is coming
    });
});

자세한 내용은 주어진 링크참조하십시오$broadcast


가장 간단한 해결책 :

AngularJS 서비스를 사용했습니다 .

1 단계 : SharedDataService라는 AngularJS 서비스를 만들었습니다.

myApp.service('SharedDataService', function () {
     var Person = {
        name: ''

    };
    return Person;
});

2 단계 : 두 개의 컨트롤러를 생성하고 위에 생성 된 서비스를 사용하십시오.

//First Controller
myApp.controller("FirstCtrl", ['$scope', 'SharedDataService',
   function ($scope, SharedDataService) {
   $scope.Person = SharedDataService;
   }]);

//Second Controller
myApp.controller("SecondCtrl", ['$scope', 'SharedDataService',
   function ($scope, SharedDataService) {
   $scope.Person = SharedDataService;
   }]);

3 단계 : 보기에서 생성 된 컨트롤러를 사용하십시오.

<body ng-app="myApp">

<div ng-controller="FirstCtrl">
<input type="text" ng-model="Person.name">
<br>Input is : <strong>{{Person.name}}</strong>
</div>

<hr>

<div ng-controller="SecondCtrl">
Input should also be here: {{Person.name}}
</div>

</body>

이 문제에 대한 해결책을 보려면 아래 링크를 누르십시오

https://codepen.io/wins/pen/bmoYLr

.html 파일 :

<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>

<body ng-app="myApp">

  <div ng-controller="FirstCtrl">
    <input type="text" ng-model="Person.name">
    <br>Input is : <strong>{{Person.name}}</strong>
   </div>

<hr>

  <div ng-controller="SecondCtrl">
    Input should also be here: {{Person.name}}
  </div>

//Script starts from here

<script>

var myApp = angular.module("myApp",[]);
//create SharedDataService
myApp.service('SharedDataService', function () {
     var Person = {
        name: ''

    };
    return Person;
});

//First Controller
myApp.controller("FirstCtrl", ['$scope', 'SharedDataService',
    function ($scope, SharedDataService) {
    $scope.Person = SharedDataService;
    }]);

//Second Controller
myApp.controller("SecondCtrl", ['$scope', 'SharedDataService',
    function ($scope, SharedDataService) {
    $scope.Person = SharedDataService;
}]);

</script>


</body>
</html>

angular.copy를 사용하여 $ watch를 사용하지 않는 다른 방법이 있습니다.

var myApp = angular.module('myApp', []);

myApp.factory('Data', function(){

    var service = {
        FirstName: '',
        setFirstName: function(name) {
            // this is the trick to sync the data
            // so no need for a $watch function
            // call this from anywhere when you need to update FirstName
            angular.copy(name, service.FirstName); 
        }
    };
    return service;
});


// Step 1 Controller
myApp.controller('FirstCtrl', function( $scope, Data ){

});

// Step 2 Controller
myApp.controller('SecondCtrl', function( $scope, Data ){
    $scope.FirstName = Data.FirstName;
});

여러 가지 방법이 있습니다.

  1. 이벤트-이미 잘 설명했습니다.

  2. UI 라우터-위에서 설명했습니다.

  3. 서비스-위에 표시된 업데이트 방법
  4. BAD- 변경 사항 감시
  5. 보다는 또 다른 부모 자식 접근 개의 발광의 브로드 캐스트 -

*

<superhero flight speed strength> Superman is here! </superhero>
<superhero speed> Flash is here! </superhero>

*

app.directive('superhero', function(){
    return {
        restrict: 'E',
        scope:{}, // IMPORTANT - to make the scope isolated else we will pollute it in case of a multiple components.
        controller: function($scope){
            $scope.abilities = [];
            this.addStrength = function(){
                $scope.abilities.push("strength");
            }
            this.addSpeed = function(){
                $scope.abilities.push("speed");
            }
            this.addFlight = function(){
                $scope.abilities.push("flight");
            }
        },
        link: function(scope, element, attrs){
            element.addClass('button');
            element.on('mouseenter', function(){
               console.log(scope.abilities);
            })
        }
    }
});
app.directive('strength', function(){
    return{
        require:'superhero',
        link: function(scope, element, attrs, superHeroCtrl){
            superHeroCtrl.addStrength();
        }
    }
});
app.directive('speed', function(){
    return{
        require:'superhero',
        link: function(scope, element, attrs, superHeroCtrl){
            superHeroCtrl.addSpeed();
        }
    }
});
app.directive('flight', function(){
    return{
        require:'superhero',
        link: function(scope, element, attrs, superHeroCtrl){
            superHeroCtrl.addFlight();
        }
    }
});

이 패턴을 어디에서 선택했는지 확실하지 않지만 컨트롤러간에 데이터를 공유하고 $ rootScope 및 $ scope를 줄이려면 이것이 효과적입니다. 게시자와 가입자가있는 데이터 복제를 연상시킵니다. 도움이 되길 바랍니다.

서비스:

(function(app) {
    "use strict";
    app.factory("sharedDataEventHub", sharedDataEventHub);

    sharedDataEventHub.$inject = ["$rootScope"];

    function sharedDataEventHub($rootScope) {
        var DATA_CHANGE = "DATA_CHANGE_EVENT";
        var service = {
            changeData: changeData,
            onChangeData: onChangeData
        };
        return service;

        function changeData(obj) {
            $rootScope.$broadcast(DATA_CHANGE, obj);
        }

        function onChangeData($scope, handler) {
            $scope.$on(DATA_CHANGE, function(event, obj) {
                handler(obj);
            });
        }
    }
}(app));

새 데이터를 가져 오는 Controller (Publisher)는 이와 같은 작업을 수행합니다.

var someData = yourDataService.getSomeData();

sharedDataEventHub.changeData(someData);

구독자라고하는이 새로운 데이터를 사용하는 컨트롤러는 다음과 같은 작업을 수행합니다.

sharedDataEventHub.onChangeData($scope, function(data) {
    vm.localData.Property1 = data.Property1;
    vm.localData.Property2 = data.Property2;
});

이것은 모든 시나리오에서 작동합니다. 따라서 기본 컨트롤러가 초기화되고 데이터를 가져 오면 changeData 메서드를 호출하여 해당 데이터의 모든 가입자에게 브로드 캐스트합니다. 이를 통해 컨트롤러의 커플 링이 줄어 듭니다.


간단하게 (v1.3.15로 테스트) :

<article ng-controller="ctrl1 as c1">
    <label>Change name here:</label>
    <input ng-model="c1.sData.name" />
    <h1>Control 1: {{c1.sData.name}}, {{c1.sData.age}}</h1>
</article>
<article ng-controller="ctrl2 as c2">
    <label>Change age here:</label>
    <input ng-model="c2.sData.age" />
    <h1>Control 2: {{c2.sData.name}}, {{c2.sData.age}}</h1>
</article>

<script>
    var app = angular.module("MyApp", []);

    var dummy = {name: "Joe", age: 25};

    app.controller("ctrl1", function () {
        this.sData = dummy;
    });

    app.controller("ctrl2", function () {
        this.sData = dummy;
    });
</script>

참고 URL : https://stackoverflow.com/questions/21919962/share-data-between-angularjs-controllers



반응형