might
@might
javascript developer

У меня не работает парочка вещей на angular, как пофиксить?

Пытаюсь изучить angular, экспериментирую ...
Косяки, которые никак не могу пофиксить:
1. При нажатии на "заказать" товар добавляется в массив, но "сумма заказа" не обновляется (если выводить не html файл через директиву, а использовать ngSwitch, то работает).
2. Поиск не работает, не могу понять в чём проблема, вроде всё верно и без ngSwitch работает.
  • Вопрос задан
  • 2323 просмотра
Решения вопроса 1
AMar4enko
@AMar4enko
Насчет того, что у вас при нажатии "Заказать" добавляется в массив, но не пересчитывается сумма заказа:
У вас mainController объявлен на body, а потом объявлен в my-directive.

В начале mainController вы в скоупе создаете новую ссылку на массив orderList, totalPrice() вызывается на скоупе второго экземпляра mainController, в то время как добавление товара происходит в массив, объявленный в скоупе первого экземпляра mainController, а это два разных массива.

А убрать из директивы объявление контроллера вы не можете, потому что для директивы запрашиваете изолированный скоуп, в который само собой функция totalPrice() из скоупа, объявленного на body, не попадает.

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

P.S. По архитектуре приложения ничего говорить не буду, не просили.

Вы столкнулись с проблемой из-за того, что захардкодили в контроллерах бизнес-логику. Это очевидный архитектурный недостаток. После его устранения у вас все начнет работать как нужно. Вам нужно вынести работу с корзиной в отдельный сервис:
module.service('Cart', function($rootScope, localStorageService){
    var 
        currencies = {rub: 10800, usd: 1}, 
        cartTotal = 0, 
        cartItems = localStorageService.get('zakaz') || [];

    function updateCartTotal(){
        var _total = 0;
        angular.forEach(cartItems, function(item){
            _total += item.price;
        });
        cartTotal  = _total;   
    }

    this.getTotal = function(currency){
        var currency = currency || 'usd';
        return cartTotal * (currencies[currency] || 1);  
    }
    this.addItem = function(item){
        cartItems.push(item);
        updateCartTotal();
        $rootScope.$broadcast('cart:updated', {cartSize: cartItems.length});       
    }
    this.removeItem = function(item){
        var idx = cartItems.indexOf(item);
        if(idx > -1){
            cartItems.splice(idx,1);
            updateCartTotal();
            $rootScope.$broadcast('cart:updated', {cartSize: cartItems.length});       
        }
    }
    this.isItemAddedAlready = function(item){
        return cartItems.indexOf(item) > -1; 
    };
    this.clear = function(){
        cartItems.length = 0;
        cartTotal = 0;
        $rootScope.$broadcast('cart:updated', {cartSize: cartItems.length});   
    }
    this.getItems = function(){
        return cartItems;
    }
});

Замечание: сейчас для поиска элемента в массиве ипользуется indexOf.
Он будет работать только когда корзина будет инициализироваться пустым массивом, потому что в этом случае при добавлении и удалении элементов будут использоваться одни и те же ссылки и равенство ссылок будет прокатывать. Для нормальной работы нужно либо писать костыль для поиска по ID, либо использовать underscore или lodash.

Теперь вы в контроллеры подключаете этот сервис через DI и везде, где нужно, используете его методы.
Для того, чтобы обновлять сумму и размер корзины делаете:
$scope.$on('cart:updated', function(event, info){
    $scope.cartTotal = Cart.getTotal(currency);
    $scope.cartSize = info.cartSize;
});

Мы бы могли сохранить ссылку на функцию сервиса у себя в контроллере и в шаблоне вызывать ее, типа {{getTotal(currency)}}, но так делать не стоит, потому что это лишний нагруженный watcher. Сейчас вы его, конечно, не почувствуете, но помнить о таких моментах надо всегда. Поэтому мы подписались на событие корзины и когда корзина изменяется, вытаскиваем нужную информацию.
Перепишите код с использованием сервиса, и увидите как он изменится в лучшую сторону. Ну а про удобство автоматизированного тестирования пока, думаю, смысла нет.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы