Общий подход заключается в преобразовании данных в длинный формат (с использованием melt()
из пакета reshape
или reshape2
) или gather()
из пакета tidyr
:
library("reshape2")
library("ggplot2")
test_data_long <- melt(test_data, id="date") # convert to long format
ggplot(data=test_data_long,
aes(x=date, y=value, colour=variable)) +
geom_line()
[/g0]
Один из способов обмена переменными между несколькими контроллерами - создать службу и ввести ее на любом контроллере, где вы хотите его использовать.
Простой пример службы:
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';
.
UPDATE: Чтобы (надеюсь) сделать вещи более ясными , вот скрипка , которая показывает пример:
--- Я знаю, что этот ответ не для этого вопроса, но я хочу, чтобы люди, которые читают этот вопрос, хотят обращаться с такими сервисами, как заводы, чтобы избежать неприятностей, делая это ----
Для этого вам нужно будет использовать Сервис или Фабрику.
Службы - это ЛУЧШАЯ ПРАКТИКА для обмена данными между не вложенными контроллерами.
Очень очень хорошо аннотация по этой теме о совместном использовании данных - это объявление объектов. Мне не повезло, потому что я упал в ловушку AngularJS, прежде чем прочитал об этом, и я был очень расстроен. Так что позвольте мне помочь вам избежать этой проблемы.
Я прочитал из «ng-book: Полная книга по AngularJS», что AngularJS ng-модели, созданные в контроллерах как голые данные, являются WRONG!
Элемент области $ A должен быть создан следующим образом:
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 document), чтобы содержать вызовы как
<div ng-model="someModel.someValue"></div> //NOTICE THE DOT.
Это очень полезно для вложенных контроллеров, если вы хотите, чтобы ваш дочерний контроллер мог изменять объект с родительского контроллера ....
Но в вашем случае вы не хотите вложенных областей, но есть аналогичный аспект для получения объектов от служб к контроллерам.
Допустим, у вас есть ваш сервис «Factory», и в обратном пространстве есть объект A, который содержит объект B, который содержит objectC.
Если с вашего контроллера вы хотите ПОЛУЧИТЬ objectC в своей области, это ошибка, чтобы сказать:
$scope.neededObjectInController = Factory.objectA.objectB.objectC;
Это не работает ... Вместо этого используйте только одну точку.
$scope.neededObjectInController = Factory.ObjectA;
Тогда , в DOM вы можете вызывать objectC из объекта A. Это наилучшая практика, связанная с заводами, и, что самое важное, это поможет избежать неожиданных и неустранимых ошибок.
Я склонен использовать ценности, довольные тем, кто может обсудить, почему это плохая идея.
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;
});
Второй подход:
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 :
Я хотел бы проиллюстрировать простые вещи на простых примерах:)
Вот очень простой пример 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;
});
И вот очень простой пример 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
Если это слишком просто, здесь является более сложным примером
Также см. Ответ здесь для комментариев о соответствующих рекомендациях
Я хотел бы внести свой вклад в этот вопрос, указав, что рекомендуемый способ обмена данными между контроллерами и даже директивами заключается в использовании сервисов (фабрик), как уже указывалось, но также мне хотелось бы чтобы дать практический пример того, как это должно быть сделано.
Вот рабочий плункер: 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>'
}
}]);
Надеюсь, этот практический и чистый ответ может быть полезен кому-то.
Помимо $ rootScope и сервисов, существует простое и простое альтернативное решение для расширения угловых для добавления общих данных:
в контроллерах:
angular.sharedProperties = angular.sharedProperties
|| angular.extend(the-properties-objects);
Эти свойства принадлежат к «угловому» объекту, отделенному от областей, и может использоваться совместно с областями и службами.
1 выгода от этого, что вам не нужно вводить объект: они доступны в любом месте сразу после вашей защиты !
Ах, у вас есть немного нового материала в качестве другой альтернативы. Это местное хранилище, и работает там, где угловые работы. Пожалуйста. (Но действительно, спасибо парню)
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 в вашем контроллере.
Есть два способа сделать это
1) Использовать get / set service
2) $scope.$emit('key', {data: value}); //to set the value
$rootScope.$on('key', function (event, data) {}); // to get the value
Решение без создания Сервиса с помощью $ rootScope:
Чтобы поделиться свойствами в приложениях Controllers, вы можете использовать Angular $ rootScope. Это еще один вариант для обмена данными, поэтому люди знают об этом.
. Предпочтительным способом обмена некоторыми функциями между контроллерами является «Сервисы», чтобы читать или изменять глобальную собственность, вы можете использовать $ 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>
Не могли бы вы также сделать свойство частью родительских объектов?
$scope.$parent.property = somevalue;
Я не говорю, что это правильно, но оно работает.
Если вы не хотите делать услугу, вы можете сделать это.
var scope = angular.element("#another ctrl scope element id.").scope();
scope.plean_assign = some_value;
Вы можете сделать это с помощью служб или фабрик. Они по существу одинаковы для некоторых основных различий. Я нашел это объяснение на thinkster.io самым простым. Простой, точный и эффективный.
Образец выше работал как шарм. Я просто сделал модификацию на случай, если мне нужно управлять несколькими значениями. Надеюсь, это поможет!
app.service('sharedProperties', function () {
var hashtable = {};
return {
setValue: function (key, value) {
hashtable[key] = value;
},
getValue: function (key) {
return hashtable[key];
}
}
});
В следующем примере показано, как передавать переменные между контроллерами сиблинга и предпринимать действия при изменении значения.
Пример использования примера: у вас есть фильтр на боковой панели, который изменяет содержимое другого представления.
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>