LINUX.ORG.RU

Angular and $http

 , ,


0

1

День добрый. Вопрос вот такой, есть в форме select в который подтягиваются даные с базы, и вот делаю естсественно

$http.get('some_url).success(function(data, status){ $scope.items = data; }).error(function(){ });

То мне после этого кода выдает консоль кучу ошибок, но все работает когда перед обращением по http я делаю $scope.items = []; Выходит в success я уже ложу data в переменную, но поидеи должно же работать и без определения заранее $scope.items.


Ну во-первых, обращаться к серверу в контроллере - это моветон.

Во-вторых, что за ошибки?

Если включить телепатию, то ты сделал биндинг на $scope.items, который не существует пока запрос не вернет результат, а страница уже отрендерилась и ангуляр пытается слинковать данные.

Dantix ★★ ()
Последнее исправление: Dantix (всего исправлений: 2)
Ответ на: комментарий от Dantix

Я делал $scope.$apply(function(){}); Просто у меня не стандартные select-ы поэтому почему-то отрабатывает по разному, для одного типа select-а это работает для другого нет. И вопрос в догонку, а где лучше обращаться к серверу?

Berdin ()
Ответ на: комментарий от Berdin

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

У селекта есть ng-options, которым можно таки успешно пользоваться.

И вопрос в догонку, а где лучше обращаться к серверу?

В сервисе. Сервис инжектить в контроллер.

angular.module('app').service('someservice', ['$http', function($http) {
  function getData() {
    return $http.get('url').then(function(result) {
      return result.data;
    }),
    function(error) {
      //error handling
    };
  }

  return {
    getData: getData
  };

}]);

///////////////////////////////

angular.module('app').controller('controller', ['$scope', 'someservice', function($scope, someservice) {
  $scope.items = [];
  someservice.getData().then(function(data) {
    $scope.items = data;
  });
}]);

Это если совсем просто, но обычно показывать страницу до того как загрузятся данные не целесообразно, поэтому можно в роутере в resolve объекте получить все давнные и потом передать их в контроллер.

Dantix ★★ ()
Последнее исправление: Dantix (всего исправлений: 1)
Ответ на: комментарий от C1nde

Есть еще идеи помимо этой как лучше решить такую задачу?

Berdin ()
Ответ на: комментарий от Dantix

Жуть, еще и на клиенте городить кучу слоев из сервисов/контроллеров итд. Какие есть реальные плюсы вынесения обращений к серверу в отдельный сервис?

Nagwal ★★★★ ()
Ответ на: комментарий от Nagwal

Какие есть реальные плюсы вынесения обращений к серверу в отдельный сервис?

Если ты обращаешься к серверу с одинаковым запросом в нескольких местах, то логично вынести код этого самого обращения в отдельную функцию. В случае с angular - в сервис, он для этого и предназначен.

Там же и кэшировать ответы можно, например.

risenshnobel ★★★ ()
Ответ на: комментарий от risenshnobel

Если ты обращаешься к серверу с одинаковым запросом в нескольких местах

То логично что с данными я буду делать немного разные операции, в зависимоти от места. А писать в двух местах $http.get(...) или service.getSomeData() имхо довольно без разницы.

Там же и кэшировать ответы можно, например.

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

Nagwal ★★★★ ()
Ответ на: комментарий от Nagwal

То логично что с данными я буду делать немного разные операции, в зависимоти от места. А писать в двух местах $http.get(...)

Иногда данные требуют дополнительной обработки. Например, сервер отдаёт даты в виде строки, а их надо привести к js-ному Date. И сервис всегда будет выдавать уже обработанные данные.

Естественно, что в примере с сервисом, который не делает ничего, смысла мало. Однако если часть запросов требует обработки, а часть нет, то лучше иметь единообразный сервис, чем в одном месте дёргать сервис, а в другом - простой $http.get. Плюс в дальнейшем, если к запросу потребуется что-то добавить, не надо будет лазить по всему коду, меняя этот get на вызов из сервиса.

Ну, видимо у меня просто другая логика в приложении. Мне наоборот крайне важно, чтобы никакие данные на клиенте не кешировались.

Хм, ну тебе не надо, а кому-то надо, задачи разные. Иногда бывает, что не страшно, если у клиента старые данные, если эти данные не критичны и обновляются раз в полгода. Зато трафик и нагрузка снижаются, а это может быть важно.

Но кэширование тут как пример.

risenshnobel ★★★ ()
Ответ на: комментарий от risenshnobel

Иногда данные требуют дополнительной обработки. Например, сервер отдаёт даты в виде строки, а их надо привести к js-ному Date. И сервис всегда будет выдавать уже обработанные данные.

Ну, как вариант. Хотя чаще всего обработка данных производится крайне по разному для разных случаев использования. По крайней мере в моем проекте сейчас так.

Однако если часть запросов требует обработки, а часть нет, то лучше иметь единообразный сервис, чем в одном месте дёргать сервис, а в другом - простой $http.get.

Я решил вопрос более радикально. Ни в одном из случаев не дергать сервис ;) А цеплять к скоупу либо напрямую данные от сервера, либо после обработки.

Nagwal ★★★★ ()
Последнее исправление: Nagwal (всего исправлений: 1)
Ответ на: комментарий от Nagwal

В основном, потому что это модно, и все коллеги за чашечкой смузи с маффинами о своих директивах, контроллерах и моделях друг другу на гей-оргиях рассказывают. Если раньше на jquery даже довольно сложный гуй лепился за вечер грохотания по клавиатуре, то теперь любая хрень делается неделю и в итоге состоит из строгих, стройных слоёв, уровней и тайеров, а после требует недельного тестирования мочой.

dr-yay ★★ ()
Ответ на: комментарий от risenshnobel

Иногда данные требуют дополнительной обработки. Например, сервер отдаёт даты в виде строки, а их надо привести к js-ному Date

А фильтры на что?

ritsufag ★★★★★ ()
Ответ на: комментарий от dr-yay

Ну, все таки ангуляр, по сравнению с голым jquery, довольно много ручной возни со сложным гуем убирает. Но вот да, все это неуемное стремление к созданию слоеного торта не там так здесь - напрягает. Вроде в родоначальнике всея layers, яве - от них потихоньку уже начали все уставать и сводить их количество к минимуму, так теперь они на клиент пытаются переползти.

Nagwal ★★★★ ()
Ответ на: комментарий от ritsufag

Да фильтры тоже не всегда нужны. Проще вообще написать что-нибудь типа:


$http.get('/someurl').success(function(data) {
    $scope.data = data.reduce(function(v, p) {...}, {});
});
Nagwal ★★★★ ()
Ответ на: комментарий от Nagwal

Ну мне кажется идеология ангулар как раз располагает для того чтобы писать это в шаблонах
1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'

Тем более можно выстраивать цепочки фильтров.

ritsufag ★★★★★ ()
Ответ на: комментарий от ritsufag

Ну мне кажется идеология ангулар как раз располагает для того чтобы писать это в шаблонах

Если шаблонов много, а преобразования везде одинаковые, то проще это делать заранее.

risenshnobel ★★★ ()
Ответ на: комментарий от ritsufag

Вот за что мне нравится ангуляр, так это за то, что можно делать как удобнее. Удобнее фильтр использовать - можно фильтр. Удобнее функцию хитрую - можно и функцию.

Nagwal ★★★★ ()
Ответ на: комментарий от risenshnobel

Все бы хорошо но одно , но

<ui-select ng-model="person.selected" theme="bootstrap" search-enabled="searchEnabled" ng-disabled="disabled">
                                        <ui-select-match>{{$select.selected.name}}</ui-select-match>
                                        <ui-select-choices repeat="person in people ">
                                            <div ng-bind-html="person.name"></div>
                                        </ui-select-choices>
                                    </ui-select>
Вот такое вот решение довелось найти, так как одна предыдущая библиотечка select-ов очень ругалась и не заводилась с ng-options, пришлось найти написаные select-ы уже на angular-е, но есть одно , но у меня не заводяться многие решения типа $http.get('url).then(callback) потому что к примеру people уже прорендерено в scope, и мне естественно стреляет ошибки типа TypeError: undefined is not a function что вполне понятно, потому что шаблон ангулар отрендерил а потом добавление эелемента scope ему не идет. И вот не знаю что теперь делать, задачу нужно выполнить или искать новый selec какой, потому что с эти видом еще всплыла одна проблема.

Berdin ()
Ответ на: комментарий от ritsufag

Такое редко бывает нужно, разные шаблоны работающие с одними данными в один момент это что вообще?

Почему в один момент? Приложение, допустим, выводит один и тот же список условных новостей на разных страницах (т.е. в разных контроллерах). Список имеет отличия по оформлению, но дата везде выводится одинаково.

Писать в каждом шаблоне фильтр лень, потом ещё менять его, когда формат меняется. Писать свой фильтр - опять же, в каждом шаблоне потом его вызывать.

Да, я знаю про директивы, но они бывают излишни.

risenshnobel ★★★ ()
Ответ на: комментарий от Berdin

Тебе скорее всего надо вешать этот компонент select-ов в момент, когда ангуляр уже гарантированно отрендерил все dom элементы. Я в похожем случае сделал так:

//Заполняем тут модель обычного html селекта

$timeout(function() {
    $scope.$emit('$render_select');
});

$scope.$on('$render_select', function(evt) {
     //А вот тут вешаем уже наш у библиотечку
});
Nagwal ★★★★ ()
Последнее исправление: Nagwal (всего исправлений: 1)
Ответ на: комментарий от Nagwal

Это даже не совсем библиотечка, если посмотришь в мой пример, я полез в исходиники это директивы написаные ангуларом, я естественно лезть править их код не буду , как бы не камильфо будет, та и времени хз сколько уйдет чтобы разобаться в чужом коде, просто жаль нету альтернативы обычных селектов которые работали бы с ангуларом, потому что обработка форм - вещь не тревиальная, много требований по UI от заказчика, поэтому стандартные html select-ы не пошли визуально, а если сторонние select-ы то они то красивые как хочет заказчик но с ангуларом конфликтуют .

Berdin ()
Ответ на: комментарий от Berdin

Ну, там я смотрю бутсрап используется, я в таком случае забиваю на селекты и просто использую бутстраповские dropdown.

http://getbootstrap.com/components/#input-groups-buttons-dropdowns

Получается вот такой примерно шаблон:

<div class="input-group">
  <div class="input-group-btn">
    <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">Тип<span class="caret"></span></button>
    <ul class="dropdown-menu" role="menu">
      <li ng-repeat="(key, value) in types"><a ng-click="setEventType(key)">{{value}}</a></li>
    </ul>
  </div>
  <input type="text" class="form-control" ng-value="types[eventModel.type]" disabled>
</div>

Где types это варианты выпадающего списка, например:

$scope.types = {
        INJECTION: 'Инъекции',
        DROPPER: 'Капельницы',
        ACTION: 'Действия',
        PROCESS_START: 'Начало процесса',
        CUSTOM: 'Произвольные события'
    };
Nagwal ★★★★ ()
Ответ на: комментарий от Dantix

Ну во-первых, обращаться к серверу в контроллере - это моветон.

Предлагаешь для каждого запроса, даже разового, создавать сервис?

holuiitipun ()
Ответ на: комментарий от holuiitipun

Зависит, конечно, если все твое приложение состоит из двух запросов и одной страницы, то бессмысленно. Но я таких приложений не пишу.

Dantix ★★ ()
Ответ на: комментарий от Nagwal

Да, возможность использования в resolve в роутинге, переиспользование кода и тестирование. Как и предыдущему оратору, если твой фронденд состоит из 2-ух запросов, то этим можно пренебречь.

Dantix ★★ ()
Ответ на: комментарий от Nagwal

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

Berdin ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.