Pull to refresh

Comments 32

По поводу использования с PHP: просто AngularJS сериализует все данные в json и передает этот json в теле POST запроса, таким образом в PHP мы его можем достать следующим образом:
PHP код
$data = json_decode(file_get_contents('php://input'), true);



По поводу контроллеров (и фабрик тоже): если в проекте будет использоваться минификация все скриптов, то описанный вами способ объявления контроллера не переживет эту минификацию, лучше так:
app.controller('SomeController', ['$scope', 'DataCache', function ($scope, DataCache) {
  ...
}]);

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

Все остальное же, ну не знаю, перевод документации?
Ну и еще. для array-нотации можно применить утилиту ngmin, которая обернет все за вас.
Вот только начал осваивать Angular и замечаю одну и ту же вещь — редко в каких примерах можно вот так просто взять кусок кода скопировать к себе и будет работать.
Какие-то везде хитрые связи, что приходится хоть чуть-чуть, но что-то исправлять.
Я раньше с подобной технологией не сталкивался, поэтому понимание Angular приходит далеко не сразу.
А в целом, конечно, Angular — классный фреймворк.

Может кто подскажет как лучше отлаживать сайт на Angular? А то мне Firefox Firebug выдает ошибки в абсолютно непонятном виде.
На самом деле, ошибок, которые стоит отлаживать, не так уж много.
Если на сайте дополнительно используется jQuery(вполне рабочая ситуация при использовании различных плагинов), то можно, например, в хроме сделать такой финт ушами:
1. Выделить элемент.
2. В консоли написать магическую строчку $($1).scope()
3. В консоль напишется значение scope, которая привязана к текущему элементу.

Почему не стоит использовать Batarang (ИМХО) — сайт начинает глючить, тормозить, и насколько мне известно, еще месяц-два назад были проблемы с утечкой памяти.

А вообще — Firebug должно хватать. Все ошибки достаточно легко локализуются обычным выключением новых директив с поиском конфликтующей (потому что проблемы возникают с их взаимодействием обыкновенно).

Из финтов ушами для получения значения внутри scope можно, пожалуй, еще вспомнить такую вещь:
<pre ng-bind="object_in_scope | 'json'"></pre>
Не совсем правильно выразился. Я имел в виде не отладку, а диагностику ошибок.
То есть что-то написал, страницу обновляю и в консоли Firebug красный текст с ошибкой на символов 200 из которого ничего не понятно.
Вот и приходится методом подбора изменять код.
Ну тут все просто. Основные типы ошибок, которые навскидку вспоминаются:
1. Не подключен модуль
2. В параметр директивы с вычислением ('=', '&') передается какая-то фигня.
3. Stack overflow при вызове вложенных scope.$digest
Все из этих проблем достаточно легко локализуются и исправляются. Ну хорошо, насчет легко исправляются я все-таки пошутил. =)
Ошибки легко гуглятся, а если Вам непонятно, из-за чего они возникли — опишите в комментарии. Быть может, я сталкивался с такой проблемой.
Возможно, я не правильно понял, но вы вручную вызываете $digest? Если да, то это плохая практика, если нужно провести какую-то манипуляцию со $scope, в месте, где AngularJS сам за этими манипуляциями не сможет уследить (к примеру $.animate, или еще что-нибудь асинхронное), то стоит использовать $scope.$apply все же.

Просто я сам никогда с ошибкой из п.3 никогда не сталкивался, часто бывает Error $scope.$digest already in progress, но не более того :)
Нет, вручную $digest я, слава богу, не вызываю. Пару раз были косяки с вложенными scope.$apply, над которыми я долго думал(как обычно, функция, внутри функции внутри функции). Каюсь, я тоже страдаю криворукостью иногда)
Ваша ошибка тоже иногда случается, да)
Ну вот к примеру,
image
Как я могу понять какая тут ошибка или я может в принципе что-то не так делаю?
Инжектор навернулся. Посмотрите, что у Вас с функцией stateProvider, какие проблемы в синтаксисе.
У меня вопрос не по этой конкретной ошибке, а в целом. Почему я не могу получить нормальную диагностику ошибок?
Я не сильно хорошо знаю JavaScript и Angular, может это в порядке вещей, тогда буду принимать это как данность. А может я что-то делаю не так.
Но почему бы не указать нормально хотя бы строку и файл, где имеются проблемы?
Это Angular получается рушиться в процессе выполнения?
Да, в процессе выполнения, потому-то все так грустно. Обычно у него есть перехватчик ошибок, который, впрочем, тоже ловит нечто невразумительное)
Как советовали в комментариях ниже — быть может, просто стоит взять 1.2.0 вместо 1.0.8.
А что говорит call stack?
Ну вот почти все, что выдало в консоль и есть ссылка, просто хромовский DevTools делает это нормальной ссылкой, кликабельной :)
Мне очень нравится как обрабатывает ошибки KnockoutJS
У меня зачастую такой текст указывает на то, что допустил глупую ошибку. Скорее всего где-то опечатка в синтаксисе
А можно узнать какую вы версию AngularJS используете? Т.к. в текущей стабильной версии 1.0.8 да, с этим проблемно, но в, скажем, 1.2.0-rc.* уже все значительно проще, если случается какая-то внутренняя ошибка, то в консоли окажется ссылочка, которая ведет на человеческое описание проблемы :)
Я пользуюсь последней версией 1.2.0. Спасибо всем за разъяснения, я понял, что можно получить более полную информацию по ошибкам, но с чем-то приходится мириться. Пока напрягает не очень сильно и думаю, что с увеличением практических навыков подобные проблемы разрешаться.
По поводу получения событий. Опишите пожалуйста, рабочую ситуацию, когда это может пригодиться.
Приведенный Вами пример включает в себя две неверные вещи при работе с ангуляром:
1. Использование angular.element в контроллере, в то время как лучше его использовать в директивах, а лучше вообще не использовать.
2. Зачем городить свой ng-class?
Когда делаю директиву-адаптер к jquery плагину, иногда приходится прокидывать $event, чтобы после отправить его в плагин, например.
По поводу StateManager, честно, так и не понял зачем он нужен, почему бы просто один раз не написать Interceptor, а все данные передавать в контроллеры через resolve.
В вашем примере StateManager не очень удобно то, что нужно не забывать удалять процессы из него.
Я написал свой велосипед, который пока руки не дошли причесать и выложить на github.

В шаблоне пишем:

<div ng-loaded="loaded">
   view content
</div>


В контроллере (я использую Restangular и ui-router) пишем:

    var users = Restangular.all('user').getList().then(function(data) {
        // do something with response
    });
    var products = Restangular.all('product').getList().then(function(data) {
        // do something with response
    });
    $scope.loaded = loadingService.add(users, products).wait();


Код
angular.module('loadingService', [])
.factory('loadingService', ['$q', '$rootScope', function($q, $rootScope) {
    var waited = [];
    $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
        waited = []; // empty array when transition to new state
    });
    return {
        add: function() {
            for(var i in arguments) {
                waited.push(arguments[i]);
            }
            return this;
        },
        wait: function() {
            var ret = $q.defer();
            $q.all(waited)['finally'](function() {
                waited = [];
                ret.resolve(1);
            });
            return ret.promise;
        }
    };
}])
.directive('ngLoaded', ['$compile', function($compile) {
    return {
        link: function(scope, element, attrs) {
            var indicator = angular.element('<div><img src="assets/loader.gif" /> Loading...</div>');
            indicator = $compile(indicator)(scope);
            element.after(indicator);
            scope.$watch(attrs.ngLoaded, function(newValue, oldValue) {
                if(newValue) {
                    element.css({display: 'block'});
                    indicator.css({display: 'none'});
                } else {
                    element.css({display: 'none'});
                    indicator.css({display: 'block'});
                }
            });
        }
    };
}])
;

Мы в m.mamba.ru делаем так:

factory('LoadRendererService', ['$rootScope', function LoadRendererService($rootScope) {
	function setFlag(isLoaded)
	{
		$rootScope.controllerDataLoaded = !! isLoaded;
	}
	function setFlagLoadError(isError)
	{
		$rootScope.controllerDataLoadError = !! isError;
	}

	return {
		setLoaded: function setLoaded()
		{
			setFlag(true);
		},
		setNotLoaded: function setLoaded()
		{
			setFlag(false);
		},
		setLoadError: function setLoadError(isError)
		{
			setFlagLoadError(isError);
		}
	};
}])

шаблон:
<div class="b-layout" ng-class="{'b-loader': ! controllerDataLoaded && ! controllerDataLoadError}">
</div>


использование в контроллере:
controller('RegisterConfirmCtrl', ['$scope', 'LoadRendererService', 'RegisterConfirmService', function RegisterConfirmCtrl($scope, LoadRendererService, RegisterConfirmService) {
	LoadRendererService.setNotLoaded();
	RegisterConfirmService.get(function (response) {
		LoadRendererService.setLoaded();
		onLoad(response);
	});
}])
UFO just landed and posted this here
Ну обычно эта логика относится непосредственно к представлению, так что это наоборот нормально. А бизнес логика должна выноситься в сервисы.
Если эта логика относится только к шаблону, то лучше бы её завернуть в директиву, там же не просто присвоение, есть какое-то поведение у DOM-а. Заодно можно будет один раз протестировать и потом повторно использовать. Если присвоение относится к бизнес-логике — то переместить в контроллер.
Опять же, передавать с запросами content-type: application/json, и на стороне сервера все такие запросы предварительно десериализовать.

p.s. каюсь, прочел только первый абзац статьи на момент комментария.
ng-cloak можно использовать как css класс и если для него иметь определение в своих стилях, то сходу не очень понятно, какие там проблемы в «большинстве» случаев.

Менеджер состояний выглядит неоднозначно. Для простейших случаев есть pendingRequests. В остальных случаях это должно архитектурно решаться, а не ручным добавлением, удалением.

Получение событий — тот случай, когда лучше бы «всякое» не случалось.

$cacheFactory — может быть им пренебрегают, потому что простейший кэш — это все же не бином Ньютона. А вот то, что $cacheFactory в AngularJS — это LRU кэш (вытеснение давно неиспользуемых) из документации можно сходу и не понять.
Как то раз мне внезапно захотелось, что бы сайт после загрузки появлялся плавно (с использованием css transition). С использованием ng-cloak этого не получилось, поэтому сделал вот так:

<div class="wrapper" ng-class="{smoothOpacity:true}">
    ...
</div>


И прописал стили:
.wrapper {
    opacity: 0;
    -moz-transition: opacity 0.6s ease;
    -o-transition: opacity 0.6s ease;
    -webkit-transition: opacity 0.6s ease;
    transition: opacity 0.6s ease;
}

.smoothOpacity {
    opacity: 1;
}


Что получилось? ng-class начинает работать только после того как Angular полностью загрузился, контент появляется плавно и довольно симпатично, все довольны. За это решение спасибо StackOverFlow.
Sign up to leave a comment.

Articles