@fantom0005

Не появляется отображается в директиве информация, что делать?

Здравствуйте. У меня есть сервис, который подгружает с сервера список ордеров. Их я решил отображать, через директиву. Но вот в чем проблема: при загрузки ордеров, я их передаю в контроллер, но они не отображаются в шаблонах.
PS. простите за coffeescript

Сам сервис

OrderS = ($http,$q,AuthService) ->
	vm = @

	vm.orders = []

	vm.getOrders = ->
		if AuthService.authorized
			deferred = $q.defer()
			$http.get('/dashboard/api/v1/orders/')
			.success (response, status, headers, config) ->
				if status == 200
					vm.orders = response
				deferred.resolve(response, status, headers, config)
			.error (response, status, headers, config) ->
				deferred.reject(response, status, headers, config)
			return deferred.promise
		else
			return null

	vm.getOrderId = (id) ->
		if vm.orders
			for item in vm.orders
				if item.id.toString() == id.toString()
					return item
		else
			return null

	vm

angular.module('dashboardApp').service 'OrderService', [
	'$http'
	'$q'
	'AuthService'
	OrderS
]


И директива с контроллером

OrderDirective = () ->
	restrict : 'E'
	controller : OrderCtrl
	controllerAs : "order"
	transclude: true
	scope:
		index: "@index"
	templateUrl: '/static/store/templates/order.html'
	link: (scope, element, attr, ctrl) ->
		ctrl.index = attr.index
		ctrl.setOrder()

angular.module('dashboardApp').directive 'order', [
	OrderDirective
]


OrderCtrl = (OrderService,$scope) ->
	vm = @

	vm.order = {}
	vm.index = ""

	vm.setOrder = (id) -> 
		vm.order = OrderService.getOrderId(vm.index)

	$scope.$watch(
		-> OrderService.getOrderId(vm.index)	
		(newValue) -> vm.setOrder(vm.index)
	)

	vm

angular.module('dashboardApp').controller 'OrderCtrl', [
	'OrderService'
	'$scope'
	LoginCtrl
]

Template большой, скидывать его не буду. Просто допустим: {{order.order.id}}.
Помогите, пожалуйста, ребята. Я себе уже весь мозг сломал. Спасибо!!
  • Вопрос задан
  • 156 просмотров
Пригласить эксперта
Ответы на вопрос 1
@bromzh
Drugs-driven development
Прежде чем что-то писать дальше на ангуляре, советую изучить styleguide и следовать ему.
Особенно плохи такие вещи:
1) использование .success/.error вместо .then в $http; Они давненько deprecated. Только .then.
2) создание лишних deferred-объектов. метод .then() и так вернёт промис.
3) в методе .getOrders твоего сервиса в одном случае возвращается промис, а в другом просто null. всегда возвращай промис. просто там, где всё плохо нужно делать reject
4) сохранять список в сервисе, а потом искать элемент по id в нём не самая хорошая идея. нужно всегда запрашивать с сервера свежие данные
В общем, твой сервис должен выглядеть примерно так:
ordersFactory.$inject = ['$http', '$q', 'AuthService'];
function ordersFactory($http, $q, AuthService) {
    return {
        getList: getList,
        
    };

    function getList() {
        // лучше, чтобы был промис
        // Выстраиваем цепочку промисов
        return AuthService.isAuthorized()  
            .then(() => $http.get('/api/orders'))  // тут шлём запрос, 
            .then(response => response.data);     // bи просто возвращаем данные ответа
            // в итоге, сервис зарезолвит промис и вернёт данные 
            // только если все в цепочке промисов зарезолвят их
            // если где-то будет reject, то его можно будет отловить выше
            // либо можно отловить reject тут и что-то сделать, тут уж тебе решать
    }

    function getById(id) {
        AuthService.isAuthorized()  // лучше делать запрос на сервер, чем пытаться найти в массиве
            .then(() => { $http.get('/api/orders/' + id))                  
            .then(response => response.data);
    }

    function getByIdInList(id) { // но если сильно хочется искать элемент на клиенте
        return getList()         // то лучше сделать так
            .then(orders => { // обрабатываем данные, полученные из getList 
                                      // при условии, что они зарезолвятся
                // тут ищем
                for (let i = 0; i < orders.length; ++i) {
                    if (orders[i].id === id) {
                        return $q.resolve(orders[i]);
                    }
                }
                return $q.reject();
            });
        
    }
}

Ну и если ты не работаешь с DOM, функция линк не нужна, контроллера директиве хватит.

Ну а ответ на твой вопрос кроется тут:
vm.setOrder = (id) -> 
    vm.order = OrderService.getOrderId(vm.index)


Получения списка заказов - асинхронная функция, завёрнутая в промис. После выполнения в сервисе у тебя будет список заказов. Но функция getOrderId - синхронная и работает без промисов.
Это неправильно. Если хоть она функция в цепочке вызовов асинхронная и возвращает промис, то нужно выстроить цепочку промисов, и в контроллере в .then уже присваивать полученные данные.

В итоге, при загрузке страницы у тебя просто может не быть списка заказов.

Если взять мой сервис, то в контроллере надо так:
OrderController.$inject = ['OrderService'];
function OrderController(OrderService) {
    var vm = this;

    OrderService.getOrderId(vm.index)
        .then((order) => {
            vm.order = order;
        })
        .catch(() => {
            vm.message = 'Заказ не найден';
        });
}
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы