Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 07.06.2013, 13:40
Интересующийся
Отправить личное сообщение для MaximusFT Посмотреть профиль Найти все сообщения от MaximusFT
 
Регистрация: 07.06.2013
Сообщений: 14

из $Scope в функцию
Изучаю Angular.

Я только делаю первые шаги, и сейчас делаю небольшое приложение, но дело в том что на многих страницах есть одинаковые $scope и соответственные функции.

Пример
$scope.items = Users.query(function(data){
		$scope.paginator.setPages($scope.items.length);
		var i = 0;
		angular.forEach(data, function(v,k) {
			data[k]._id = i++;
		});
	});

или
$scope.sortBy = function() {
		var order = [];
		angular.forEach($scope.tablehead, function(h){
			if (h.sort>0) order[h.sort-1] = h.name;
			if (h.sort<0) order[Math.abs(h.sort)-1] = '-'+h.name;
		});
		return order;
	};


Но дубляж кода не есть хорошо, решил уменьшить код, сделать функции из этих скопов, но ни в какую, только ошибки в консоли в формате что не может вызвать $scope из функции пишет что "TypeError: Cannot call method 'slice' of undefined..."

slice это метод, он есть если вызывать $scope из примеров внутри контроллера...

Подскажите как можно сделать из Скопа - функцию чтобы внутри нее можно было вызывать другие Скопы и с ними работать.
Ответить с цитированием
  #2 (permalink)  
Старый 07.06.2013, 21:20
Новичок на форуме
Отправить личное сообщение для just-boris Посмотреть профиль Найти все сообщения от just-boris
 
Регистрация: 03.06.2013
Сообщений: 5

Для начала, в angular есть встроенный сортировщик - orderBy.
А насчет ошибки, расскажите, пожалуйста, как вы вызываете функцию и саму эту функцию.
Ответить с цитированием
  #3 (permalink)  
Старый 07.06.2013, 22:25
Интересующийся
Отправить личное сообщение для MaximusFT Посмотреть профиль Найти все сообщения от MaximusFT
 
Регистрация: 07.06.2013
Сообщений: 14

Контроллер страницы
function sortReorder(col,e,scope) {
	if (e.shiftKey) {
		var sortIndex = 0;
		angular.forEach(scope, function(el) {
			if (Math.abs(el.sort)>sortIndex) sortIndex = Math.abs(el.sort);
		});
		angular.forEach(scope, function(el) {
			if (el.name==col) el.sort = el.sort?-el.sort:sortIndex+1;
		});
	} else {
		angular.forEach(scope, function(el) {
			if (el.name==col) el.sort = el.sort>0?-1:1; else el.sort = null;
		});
	}
};
function UsersCtrl($scope, $routeParams, $location, Users) {
	$scope.items = Users.query(function(data){
		$scope.paginator.setPages($scope.items.length);
		var i = 0;
		angular.forEach(data, function(v,k) {
			data[k]._id = i++;
		});
	});

	$scope.selected  = [];
	$scope.paginator = {
		count: 20,
		page:  1,
		pages: 1,
		setPages: function(itemsCount){ this.pages = Math.ceil(itemsCount/this.count); }
	};
	
	$scope.sortBy = function() {
		var order = [];
		angular.forEach($scope.tablehead, function(h){
			if (h.sort>0) order[h.sort-1] = h.name;
			if (h.sort<0) order[Math.abs(h.sort)-1] = '-'+h.name;
		});
		return order;
	};
	$scope.sortReorder = function(col,e) { sortReorder(col,e,$scope.tablehead);	};
}


Обратите внимание на sortReorder, это удалось превратить в функцию... и вызывать ее в разных контроллерах...
А вот из вот этого
$scope.sortBy = function() {
		var order = [];
		angular.forEach($scope.tablehead, function(h){
			if (h.sort>0) order[h.sort-1] = h.name;
			if (h.sort<0) order[Math.abs(h.sort)-1] = '-'+h.name;
		});
		return order;
	};


не получается, и вот из этого в особенности хочется, так как это то что может правильно перегрузить содержимое таблицы на странице
$scope.items = Users.query(function(data){
		$scope.paginator.setPages($scope.items.length);
		var i = 0;
		angular.forEach(data, function(v,k) {
			data[k]._id = i++;
		});
	});


Оба кода уникальны для всех страниц, сейчас у меня их уже 8... и в каждом контроллере страницы есть одинаковые куски кода...

Я понимаю что может я говорю как Ламер... но я очень хочу разобраться...
Ответить с цитированием
  #4 (permalink)  
Старый 08.06.2013, 00:07
Новичок на форуме
Отправить личное сообщение для just-boris Посмотреть профиль Найти все сообщения от just-boris
 
Регистрация: 03.06.2013
Сообщений: 5

я правильно понял, что вы хотите вызвать sortReorder в функции $scope.sortBy?
Ответить с цитированием
  #5 (permalink)  
Старый 08.06.2013, 08:47
Профессор
Отправить личное сообщение для Shitbox2 Посмотреть профиль Найти все сообщения от Shitbox2
 
Регистрация: 04.10.2010
Сообщений: 557

Кажется, что-то тут не так... $scope только для чтения в шаблонах и только для записи в контроллере. Вы же в своих функциях используете область видимости для получения данных. Тогда уж нужно присвоить модель переменной и работать уже с ней.
var model = Users.query(function(data){
$scope.items = model

Возможно, имеет смысл создать собственный фильтр и использовать его в контроллере с помощью сервиса $filter
Ответить с цитированием
  #6 (permalink)  
Старый 09.06.2013, 14:05
Профессор
Отправить личное сообщение для Shitbox2 Посмотреть профиль Найти все сообщения от Shitbox2
 
Регистрация: 04.10.2010
Сообщений: 557

Еще перевел статью по областям видимости: http://www.angular.ru/guide/understanding_scopes. Там как раз говорится о том, как пользоваться областями
Ответить с цитированием
  #7 (permalink)  
Старый 10.06.2013, 06:38
Профессор
Отправить личное сообщение для DjDiablo Посмотреть профиль Найти все сообщения от DjDiablo
 
Регистрация: 04.02.2011
Сообщений: 1,815

Не знаю правильно ли я понял вопрос

Но если у тебя есть общие куски кода в нескольких контролёрах тогда создайте собственный модуль с нужными методами и подключайте его в тех контролёрах где он вам необходим. Это обыкновенное модульное программирование.

вот кстатии хороший пример. http://www.angular.ru/guide/dev_guid...ng_controllers

Сервис предоставляющий множество методов можно как нибудь так описать
angular.module('MyServiceModule', []).
 factory('notify', function() {
    
    return {
         fync1:function(){},
         fync2:function(){},
         fync3:function(){}
    }

  });


либо

angular.module('MyServiceModule', []).
 factory('notify', function() {
    var f=function(){
       //бла бла
    },
    p=f.prototype;
    p.func1=function(){};
    p.func2=function(){};

    return new f();
    //return f; если хочешь сам вызывать конструктор из контрола
  });


3) Можно создать сервис users который будет возвращать не только данные но и методы работы с ними.(вероятно идеальное решение)

4) Придумал ещё один ход подобный примесям. Но сам бы я его пожалуй избегал до последнего.

angular.
 module('MyServiceModule', []).
 factory('extendScope',function() {    

    return function(scope) {
        scope.fn1=function(){};
        scope.fn2=function(){};
        scope.fn3=function(){};
        return scope;
    }   
  });
function myController(scope, extendScope) {
  extendScope(scope);
  // или scope=extendScope(scope);
}
__________________
Лучше калымить в гандурасе чем гандурасить на колыме

Последний раз редактировалось DjDiablo, 10.06.2013 в 07:47.
Ответить с цитированием
  #8 (permalink)  
Старый 11.06.2013, 14:03
Интересующийся
Отправить личное сообщение для MaximusFT Посмотреть профиль Найти все сообщения от MaximusFT
 
Регистрация: 07.06.2013
Сообщений: 14

Спасибо большое за советы, наверное мне не хватает банальных знаний об Объектах.
Можно еще один вопрос:

<div class="span6" ng-controller="MyCtrl14">
	MyCtrl14 > block14 = 
	<br>
	<button ng-click="aMyCtrl14()">- ! -</button>
	<br>
	{{block14}}
	<div class="row show-grid">
		<div class="span3">
			IndexCtrl > block141 =
			<br>
			{{block141}}
		</div>
		<div class="span3" ng-controller="MyCtrl142">
			MyCtrl142 > block142 =
			<br>
			<button ng-click="aMyCtrl142()">- ! -</button>
			<br>
			{{block142}}
		</div>
	</div>
</div>

function MyCtrl14($scope, notify) {
	$scope.block141 = '111';
	$scope.aMyCtrl14 = function(){
		$scope.block141 = '333';
		$scope.block142 = '444';
	}
}
function MyCtrl142($scope, newnoty) {
	$scope.aMyCtrl142 = function(){
		$scope.block141 = '555';
		$scope.block142 = '666';
	}
}


1) Нажимаем на кнопку "aMyCtrl14" - она вставляет оба значения block141 и block142.
2) Нажимаем на кнопку "aMyCtrl142" - она обновляет только значение block142.
Понятно так как дочерняя не имеет по умолчанию возможности работать с областью родителей. НО!
3) Нажимаем на кнопку "aMyCtrl14" - она обновляет только значение block141.
Почем Родитель теряет власть над областью после того как в нее было что-то записано дочерним контроллером...

Подскажите как можно обновлять информацию из одного контроллера в другом?

Последний раз редактировалось MaximusFT, 11.06.2013 в 15:08.
Ответить с цитированием
  #9 (permalink)  
Старый 15.06.2013, 16:02
Новичок на форуме
Отправить личное сообщение для just-boris Посмотреть профиль Найти все сообщения от just-boris
 
Регистрация: 03.06.2013
Сообщений: 5

Потому что пока значение не определено, оно ищется у родителей вверх по цепочке. Потом оно перезаписывается локальным и больше не зависит от родителей.
Ответить с цитированием
  #10 (permalink)  
Старый 15.06.2013, 16:19
Интересующийся
Отправить личное сообщение для MaximusFT Посмотреть профиль Найти все сообщения от MaximusFT
 
Регистрация: 07.06.2013
Сообщений: 14

А принудительно как внести изменения в дочернем элементе?
Может проще отказаться от 2-х Контроллеров и делать все в одном?
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
передать анонимную функцию, вызывающую другую функцию с нужными параметрами Ваяс Общие вопросы Javascript 5 21.02.2013 18:12
Выполнить функцию заранее неизвестную Neokortex jQuery 2 13.02.2012 10:41
checkbox включен запускаем одну функцию выключен другую Sadist_dead Элементы интерфейса 11 27.09.2011 09:46
проблема с передачей параметров в функцию bartonom Элементы интерфейса 4 19.09.2011 11:41
Как получить указатель на элемент вызвавший функцию pelayo Общие вопросы Javascript 9 29.06.2010 22:32