it-swarm.com.ru

AngularJS: Как я могу передавать переменные между контроллерами?

У меня есть два Angular контроллера:

function Ctrl1($scope) {
    $scope.prop1 = "First";
}

function Ctrl2($scope) {
    $scope.prop2 = "Second";
    $scope.both = Ctrl1.prop1 + $scope.prop2; //This is what I would like to do ideally
}

Я не могу использовать Ctrl1 внутри Ctrl2, потому что он не определен. Однако, если я попытаюсь передать это так ...

function Ctrl2($scope, Ctrl1) {
    $scope.prop2 = "Second";
    $scope.both = Ctrl1.prop1 + $scope.prop2; //This is what I would like to do ideally
}

Я получаю ошибку. Кто-нибудь знает как это сделать?

Дела

Ctrl2.prototype = new Ctrl1();

Также не удается.

ПРИМЕЧАНИЕ: Эти контроллеры не вложены друг в друга.

324
dopatraman

Один из способов обмена переменными между несколькими контроллерами - создать сервис и внедрить его в любой контроллер, где вы хотите его использовать.

Простой пример обслуживания:

angular.module('myApp', [])
    .service('sharedProperties', function () {
        var property = 'First';

        return {
            getProperty: function () {
                return property;
            },
            setProperty: function(value) {
                property = value;
            }
        };
    });

Использование службы в контроллере:

function Ctrl2($scope, sharedProperties) {
    $scope.prop2 = "Second";
    $scope.both = sharedProperties.getProperty() + $scope.prop2;
}

Это очень хорошо описано в этот блог (Урок 2 и в частности).

Я обнаружил, что если вы хотите связать эти свойства с несколькими контроллерами, это будет работать лучше, если вы связываетесь со свойством объекта вместо примитивного типа (логический, строковый, числовой), чтобы сохранить привязанную ссылку.

Пример: var property = { Property1: 'First' }; вместо var property = 'First';.


ОБНОВЛЕНИЕ: Чтобы (надеюсь) прояснить ситуацию вот скрипка , которая показывает пример:

  • Связывание со статическими копиями общего значения (в myController1)
    • Привязка к примитиву (строка)
    • Привязка к свойству объекта (сохраняется в переменной области)
  • Связывание с общими значениями, которые обновляют пользовательский интерфейс при обновлении значений (в myController2)
    • Привязка к функции, которая возвращает примитив (строку)
    • Привязка к свойству объекта
    • Двухсторонняя привязка к свойству объекта
500
Gloopy

Мне нравится иллюстрировать простые вещи простыми примерами :)

Вот очень простой пример Service:


angular.module('toDo',[])

.service('dataService', function() {

  // private variable
  var _dataObj = {};

  // public API
  this.dataObj = _dataObj;
})

.controller('One', function($scope, dataService) {
  $scope.data = dataService.dataObj;
})

.controller('Two', function($scope, dataService) {
  $scope.data = dataService.dataObj;
});

И здесь jsbin

И вот очень простой пример Factory:


angular.module('toDo',[])

.factory('dataService', function() {

  // private variable
  var _dataObj = {};

  // public API
  return {
    dataObj: _dataObj
  };
})

.controller('One', function($scope, dataService) {
  $scope.data = dataService.dataObj;
})

.controller('Two', function($scope, dataService) {
  $scope.data = dataService.dataObj;
});

И здесь jsbin


Если это слишком просто, вот более сложный пример

Также см. Ответ здесь для связанных комментариев лучших методов

44
Dmitri Zaitsev

--- Я знаю, что этот ответ не для этого вопроса, но я хочу, чтобы люди, которые читают этот вопрос и хотят обращаться с такими службами, как фабрики, чтобы избежать проблем с этим --- -

Для этого вам нужно будет использовать Сервис или Фабрику.

Службы ЛУЧШАЯ ПРАКТИКА для обмена данными между не вложенными контроллерами.

Очень хорошая аннотация на эту тему об обмене данными о том, как объявлять объекты. Мне не повезло, потому что я попал в ловушку AngularJS, прежде чем я прочитал об этом, и я был очень расстроен. Итак, позвольте мне помочь вам избежать этой проблемы.

Из "ng-book: полная книга по AngularJS" я прочитал, что ng-модели AngularJS, созданные в контроллерах как голые данные, НЕПРАВИЛЬНЫ!

Элемент $ scope должен быть создан следующим образом:

angular.module('myApp', [])
.controller('SomeCtrl', function($scope) {
  // best practice, always use a model
  $scope.someModel = {
    someValue: 'hello computer'
  });

И не так:

angular.module('myApp', [])
.controller('SomeCtrl', function($scope) {
  // anti-pattern, bare value
  $scope.someBareValue = 'hello computer';
  };
});

Это потому, что рекомендуется (ЛУЧШАЯ ПРАКТИКА) для DOM (html-документ) содержать вызовы как

<div ng-model="someModel.someValue"></div>  //NOTICE THE DOT.

Это очень полезно для вложенных контроллеров, если вы хотите, чтобы ваш дочерний контроллер мог изменять объект из родительского контроллера ....

Но в вашем случае вам не нужны вложенные области видимости, но есть аналогичный аспект для передачи объектов из сервисов в контроллеры.

Допустим, у вас есть сервис "Фабрика", и в возвращаемом пространстве есть объект A, который содержит объект B, который содержит объект C.

Если из вашего контроллера вы хотите получить objectC в вашу область, было бы ошибкой сказать:

$scope.neededObjectInController = Factory.objectA.objectB.objectC;

Это не сработает ... Вместо этого используйте только одну точку.

$scope.neededObjectInController = Factory.ObjectA;

Затем в DOM вы можете вызвать objectC из objectA. Это лучшая практика, относящаяся к фабрикам, и, самое главное, она поможет избежать непредвиденных и неуловимых ошибок.

26
AFP_555

Решение без создания Сервиса с использованием $ rootScope:

Для совместного использования свойств через контроллеры приложения вы можете использовать Angular $ rootScope. Это еще один вариант обмена данными, чтобы люди знали об этом.

Предпочтительный способ обмена некоторыми функциями между контроллерами - это службы, для чтения или изменения глобального свойства вы можете использовать $ rootcope.

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>
17
Sanjeev

Пример выше работал как шарм. Я только что сделал изменение на тот случай, если мне нужно управлять несколькими значениями. Надеюсь, это поможет!

app.service('sharedProperties', function () {

    var hashtable = {};

    return {
        setValue: function (key, value) {
            hashtable[key] = value;
        },
        getValue: function (key) {
            return hashtable[key];
        }
    }
});
8
Juan Zamora

Я склонен использовать ценности, рад, что кто-нибудь обсудит, почему это плохая идея.

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

myApp.value('sharedProperties', {}); //set to empty object - 

Затем введите значение согласно услуге.

Установить в ctrl1:

myApp.controller('ctrl1', function DemoController(sharedProperties) {
  sharedProperties.carModel = "Galaxy";
  sharedProperties.carMake = "Ford";
});

и доступ из ctrl2:

myApp.controller('ctrl2', function DemoController(sharedProperties) {
  this.car = sharedProperties.carModel + sharedProperties.carMake; 

});
6
Chilledflame

Я хотел бы внести свой вклад в этот вопрос, указав, что рекомендуемый способ обмена данными между контроллерами и даже директивами - это использование сервисов (фабрик), как это уже указывалось, но я также хотел бы предоставить Рабочий практический пример того, как это должно быть сделано.

Вот рабочий планер: http://plnkr.co/edit/Q1VdKJP2tpvqqJL1LF6m?p=info

Во-первых, создайте свою службу , которая будет иметь общие данные :

app.factory('SharedService', function() {
  return {
    sharedObject: {
      value: '',
      value2: ''
    }
  };
});

Затем просто вставьте его в свои контроллеры и получите общие данные в своей области:

app.controller('FirstCtrl', function($scope, SharedService) {
  $scope.model = SharedService.sharedObject;
});

app.controller('SecondCtrl', function($scope, SharedService) {
  $scope.model = SharedService.sharedObject;
});

app.controller('MainCtrl', function($scope, SharedService) {
  $scope.model = SharedService.sharedObject;
});

Вы также можете сделать это для ваших директив , это работает так же:

app.directive('myDirective',['SharedService', function(SharedService){
  return{
    restrict: 'E',
    link: function(scope){
      scope.model = SharedService.sharedObject;
    },
    template: '<div><input type="text" ng-model="model.value"/></div>'
  }
}]);

Надеюсь, что этот практичный и чистый ответ может быть полезным для кого-то.

4
Fedaykin

В следующем примере показано, как передать переменные между siblings контроллерами и предпринять действие при изменении значения.

Пример использования: у вас есть фильтр на боковой панели, который изменяет содержимое другого представления.

angular.module('myApp', [])

  .factory('MyService', function() {

    // private
    var value = 0;

    // public
    return {
      
      getValue: function() {
        return value;
      },
      
      setValue: function(val) {
        value = val;
      }
      
    };
  })
  
  .controller('Ctrl1', function($scope, $rootScope, MyService) {

    $scope.update = function() {
      MyService.setValue($scope.value);
      $rootScope.$broadcast('increment-value-event');
    };
  })
  
  .controller('Ctrl2', function($scope, MyService) {

    $scope.value = MyService.getValue();

    $scope.$on('increment-value-event', function() {    
      $scope.value = MyService.getValue();
    });
  });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app="myApp">
  
  <h3>Controller 1 Scope</h3>
  <div ng-controller="Ctrl1">
    <input type="text" ng-model="value"/>
    <button ng-click="update()">Update</button>
  </div>
  
  <hr>
  
  <h3>Controller 2 Scope</h3>
  <div ng-controller="Ctrl2">
    Value: {{ value }}
  </div>  

</div>
4
Zanon

Вы можете сделать это с помощью услуг или заводов. Они по сути одинаковы для некоторых основных различий. Я нашел это объяснение на thinkster.io наиболее простым для подражания. Просто, точно и эффективно.

3
Noahdecoco

Не могли бы вы также сделать свойство частью родительского объекта?

$scope.$parent.property = somevalue;

Я не говорю, что это правильно, но это работает.

2
SideFX

Ах, есть немного этого нового материала в качестве другой альтернативы. Это локальное хранилище, и работает там, где работает angular. Пожалуйста. (Но на самом деле, спасибо парню)

https://github.com/gsklee/ngStorage

Определите ваши значения по умолчанию:

$scope.$storage = $localStorage.$default({
    prop1: 'First',
    prop2: 'Second'
});

Доступ к значениям:

$scope.prop1 = $localStorage.prop1;
$scope.prop2 = $localStorage.prop2;

Сохраните значения

$localStorage.prop1 = $scope.prop1;
$localStorage.prop2 = $scope.prop2;

Не забудьте ввести ngStorage в свое приложение и $ localStorage в свой контроллер.

2
kJamesy

Второй подход:

angular.module('myApp', [])
  .controller('Ctrl1', ['$scope',
    function($scope) {

    $scope.prop1 = "First";

    $scope.clickFunction = function() {
      $scope.$broadcast('update_Ctrl2_controller', $scope.prop1);
    };
   }
])
.controller('Ctrl2', ['$scope',
    function($scope) {
      $scope.prop2 = "Second";

        $scope.$on("update_Ctrl2_controller", function(event, prop) {
        $scope.prop = prop;

        $scope.both = prop + $scope.prop2; 
    });
  }
])

HTML:

<div ng-controller="Ctrl2">
  <p>{{both}}</p>
</div>

<button ng-click="clickFunction()">Click</button>

Для более подробной информации см. Plunker:

http://plnkr.co/edit/cKVsPcfs1A1Wwlud2jtO?p=preview

1
Codiee

Есть два способа сделать это

1) Воспользуйтесь сервисом get/set

2) $scope.$emit('key', {data: value}); //to set the value

 $rootScope.$on('key', function (event, data) {}); // to get the value
1
Rohan Kawade

Если вы не хотите оказывать услуги, вы можете сделать это так.

var scope = angular.element("#another ctrl scope element id.").scope();
scope.plean_assign = some_value;
0
thanksnote