Ответы пользователя по тегу Angular
  • Возможно ли non-SPA приложение на Angular2?

    @bromzh
    Drugs-driven development
    Ну второй ангуляр без костылей можно на сервере рендерить.
    Также можно сделать корневой компонент с шаблоном <ng-content></ng-content> и селектором 'body'. Хотя да, если нужен только View-слой, то нужно брать соотв. инструмент (react, polymer, etc).
    Ответ написан
    Комментировать
  • Best practice по структуре и сборке проекта?

    @bromzh
    Drugs-driven development
    Надо сразу отделить серверную часть от клиентской.
    Серверную часть сделать в виде АПИ (обычно это какой-то JSON API). Забыть про шаблонизаторы и прочее.
    Клиент работает с сервером только через АПИ.

    Т.е. как минимум будут 2 проекта со своими репозиториями (в идеале). Каждая часть не зависит от другой, может разрабатываться отдельно и при необходимости, можно заменить одну из частей не меняя другую (главное, чтобы апи остался тем же).
    Ответ написан
    1 комментарий
  • Angular2. Как в роутере передать параметр в компонент (@Input)?

    @bromzh
    Drugs-driven development
    Никак. Можно передать данные в конфиге роута в поле data, а из компонента получать эти данные например в методе жизненного цикла OnActivate, или просто внедрить зависимость RouteData и получить данные в конструкторе.
    Ответ написан
    2 комментария
  • Как долго будут развивать и поддерживать Angular.js первой серии?

    @bromzh
    Drugs-driven development
    Пару лет подержат на плаву, но новые фичи появляться вряд ли будут. Используй вторую, она намного лучше.
    Ответ написан
    Комментировать
  • Инджект сервиса в сервис в angular 2?

    @bromzh
    Drugs-driven development
    Нет, естественно надо указать только то, что будешь внедрять непосредственно в сам компонент. А можно даже не указывать ничего, если сервис ты регистрируешь глобально в функции bootstrap.

    Вообще логика такая: все сервисы, которые внедряются, должны каким-то образом быть зарегистрированы. Те сервисы, которые ты зарегистрировал глобально в функции bootstrap будут доступны глобально во всех компонентах. Их необязательно описывать в поле providers. Если сервисы не регистрируются глобально, то нужно регистрировать в компоненте. Причём сервисы будут доступны и в дочерних компонентах.
    Вообще, у каждого компонента свой инжектор зависимостей. Таким образом, для каждого компонента можно настроить провайдеры сервисов по-своему. Если сервис не зарегистрирован у компонента, то его ищут вверх по иерархии компонентов.
    Ответ написан
    4 комментария
  • Angular2 как сделать server side rendering?

    @bromzh
    Drugs-driven development
    https://github.com/angular/universal-starter
    В файле src/server.ts все ответы. Суть такая:
    1) создаём express-приложение
    let app = express();
    2) настраиваем обработку .html-файлов на ангуляровский рендерер из universe
    app.engine('.html', expressEngine);
    app.set('views', __dirname);
    app.set('view engine', 'html');

    3) Создаём функцию-обработчик, которая будет рендерить ангуляр-приложение на сервере, если пользователь зайдёт по определённым ссылкам
    function ngApp(req, res) {
      let baseUrl = '/';
      let url = req.originalUrl || '/';
      res.render('index', {
        directives: [ Html ],
        ...
      }
    }

    4) В этой функции каким-то образом надо подключить корневой компонент App. В приведённой ссылке это делается так: создаётся компонент Html (src/server-only-app/html.component.ts), который содержит полностью весь код index.html (кроме тегов html). Можно было просто в функцию ngApp указать в поле directives корневой компонент.
    5) Запускаем приложуху
    app.use(express.static(root, {index: false}));
    
    // Routes with html5pushstate
    app.use('/', ngApp);
    app.use('/about', ngApp);
    app.use('/home', ngApp);
    
    // Server
    app.listen(3000, () => {
      console.log('Listen on http://localhost:3000');
    });
    Ответ написан
    3 комментария
  • Как инициализировать SELECT со значением, а не объектом?

    @bromzh
    Drugs-driven development
    Очень корявое решение. Селект связан с полем 'select', вот в контроллере и устанавливай нужное начальное значение:
    $scope.types = [{
        id: 1,
        name: 'test1'
      }, {
        id: 2,
        name: 'test2'
      }, {
        id: 3,
        name: 'test3'
      }, {
        id: 4,
        name: 'test4'
      }, ];
    $scope.select = $scope.types[1];


    Ну и стоило бы изучить это.
    Ответ написан
    Комментировать
  • Можно ли уже использовать Angular2?

    @bromzh
    Drugs-driven development
    Вполне можно.
    Проблемы конечно ещё есть, но небольшие.

    Хотя 10-ю и 11-ю бету сложно правильно запустить, из-за зависимости от zone.js ^0.6.4: в зоне поломали обратную совместимость и typings-файлы неправильные. Так что лучше пока взять бету 9, или использовать временные хаки
    Ответ написан
    Комментировать
  • AngularJS (frontend) + Flask (backend): поднять два сервера или один?

    @bromzh
    Drugs-driven development
    1) Что за фронтенд-сервер? Типа только статика?
    2) Статику надо отдавать через nginx штатными средствами
    3) Сервер фласка нужен только для разработки. Запускать его в прод очень плохо. Flask-приложение реализует стандарт wsgi, так что его можно запустить на любом wsgi-сервере (рекомендую uwsgi). Причём желательно не выставлять его наружу, а поставить "позади" nginx, т.е. надо проксировать с nginx на uwsgi.
    Ответ написан
    Комментировать
  • Как использовать $http в es6 классе?

    @bromzh
    Drugs-driven development
    Подключаешь ngAnnotate и

    export default class ThingFactory {
      // @ngInject
      constructor($http) {
      }
    }
    // ИЛИ
    export default class ThingFactory {
      constructor($http) {
        "ngInject";
      }
    }
    Ответ написан
    Комментировать
  • Как настроить роутинг родитель+потомок в Angular 2?

    @bromzh
    Drugs-driven development
    1) Чтобы AsyncRouter не грузил файлы, в параметре loader нужно не компонент резолвить, а использовать какой-нибудь загрузчик модулей ведь если ты в коде импортируешь компонент Tables, то он уже будет включён в итоговую сборку, так что нужно импортировать не напрямую из ts, а через загрузчики, которые умеют работать в браузерной среде. Например, System.import из SystemJS. Или Вебпаковский. Пример SystemJS тут, а пример для вебпака тут.

    2) Сжимается всё например через UglifyJS, плагины для многих сборщиков есть. Но лучше сразу перейди на вебпак. Там есть классные оптимизаторы в комплекте. Например, dedupe-плагин удаляет дубликаты кода, если они встретятся, а uglify вебпаковский ещё и удаляет неиспользуемый код (он анализирует подключённые модули и вырезает неиспользуемые). У меня после всех оптимизаций чистый helloworld на ангуляре занимает 500кб и ещё 100кб полифиллы.
    Ответ написан
    2 комментария
  • Как соединить Angular и Node.js( Express)?

    @bromzh
    Drugs-driven development
    вот работающий starter-kit: https://github.com/angular/universal-starter
    ну и ещё tsd мёртв, бери typings
    Ответ написан
    Комментировать
  • На чем лучше реализовывать таблицы для Angular?

    @bromzh
    Drugs-driven development
    ui-grid.info
    lorenzofox3.github.io/smart-table-website
    ng-table.com

    Я пользовался первой, но идеальной нет, везде свои недостатки. Если все данные приходят с сервера, и пагинация, сортировка и фильтрация тоже серверные, то легче тупо вручную делать.
    Ответ написан
    6 комментариев
  • Не появляется отображается в директиве информация, что делать?

    @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 = 'Заказ не найден';
            });
    }
    Ответ написан
    Комментировать
  • Лучший ресурс/книга/видеоуроки для изучения AngularJS?

    @bromzh
    Drugs-driven development
    Читаешь и запоминаешь это
    Гуглишь про каждый пункт отсюда
    Попутно пишешь как можно больше приложений.
    Если думаешь, что начать писать можно только после кучи теории - так и останешься в теоретиках.
    Ответ написан
    Комментировать
  • В чем разница написания myApp.controller('ctrl', ['$scope', function ($scope) {}]) и myApp.controller('ctrl', function ($scope) {})?

    @bromzh
    Drugs-driven development
    Потому что ангуляр внедряет зависимости по именам аргументов. А некоторые минификаторы и компиляторы изменяют имена аргументов. В итоге всё ломается. Первый вариант используется, чтобы явно задать список имён зависимостей для внедрения.

    А вообще, по-нормальному используют либо такой вариант:
    angular.module('app').controller('FooController', FooController);
    
    FooController.$inject = ['$service1', '$service2'];
    function FooController($service1, $service2) {}


    Либо берут это, настраивают свой сборщик (плагинов там куча) и вставляют определённый коммент где нужно:
    angular.module('app').controller('FooController', FooController);
    
    /*@ngInject*/
    function FooController($service1, $service2) {}
    Ответ написан
    Комментировать
  • Как обновить данные в таблице после запроса $http.post в AngularJS?

    @bromzh
    Drugs-driven development
    0) Сперва почитай это
    1) Зачем 2 контроллера? Достаточно 1 контроллера с 2-мя методами в нём.
    2) $scope - зло. Используй синтаксис controllerAs
    3) После добавления элемента нужно либо возвращать с бэкенда новый список (что не по REST), либо делай запрос (естественно в цепочке промисов). Ведь если данные обновятся с 2-х источников, будет рассинхрон.
    4) Не используй $http().success, всегда используй then.
    5) <a href="{{x.url}}"> не сработает. Нужна директива ng-href.

    Ну а код будет примерно такой:
    function myService($http, $log) {
        return {
            addLink: addLink,
            getLinks: getLinks
        };
        
        function addLink(data) {
            $http.post('/api/links', data)
            .then(function (response) {
                $log.log('Success', response);
            });
        }
    
        function getLinks() {
            $http.get('/api/links')
            .then(function (response) {
                return response.data.records;
            });
        }
    }
    
    function MainController(myService) {
        var vm = this;
    
        vm.addLink = addLink;
    
        function fetch() {
            return myService.getLinks()
            .then(function (links) {
                vm.links = links;
            });
        }
    
        function addLink() {
            return myService.addLink({
                'linkname': vm.linkname, 
                'url': vm.url
            })
            .then(function () {
                vm.linkname = '';
                vm.url = '';
                return fetch();
            });
        }
    }
    
    angular.module('app', [])
        .factory('myService', myService)
        .controller('MainController, MainController');

    <div ng-controller="MainController as main">
        <form ng-submit="main.addLink()">
            Name: <input type="text" ng-model="main.linkname"><br>
            URL: <input type="text" ng-model="main.url">
        </form>
        <hr>
        <ul>
            <li ng-repeat="item in main.links">
                <a ng-href="{{ item.url }}">{{ item.linkname }}</a>
            </li>
        </ul>
    </div>
    Ответ написан
    1 комментарий