• Инджект сервиса в сервис в 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 комментария
  • Как правильно связать два объекта в Mongoose (MongoDB)?

    @bromzh
    Drugs-driven development
    Что я делаю не так?

    Используешь монго там где не надо.
    Как правильно сохранять объекты со связями?

    Взять реляционную БД. В самом названии есть намёк, что такие БД хорошо подходят для хранения объектов со связями.

    Вот какой смысл брать монгу и пытаться построить архитектуру в стиле реляционных БД? Что мешает хранить story в поле документа юзера?
    Ответ написан
  • Как инициализировать 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.
    Ответ написан
    Комментировать
  • Как реализовать кнопку/ссылку с таймером?

    @bromzh
    Drugs-driven development
    Ответ написан
    Комментировать
  • Как использовать $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 комментария
  • Как импортировать тесты с es6 модулями?

    @bromzh
    Drugs-driven development
    Можно настроить вебпак соответствующим образом.
    См. в этом репозитории на файл spec.bundle.js. В настройках кармы подключается только этот файл. В самом же файле:
    1) Создаётся функция-контекст. require.context составляет список файлов в соответствии с параметрами (1-й - корневая директория, где будут искаться файлы, 2-й - рекурсивно или нет искать файлы и 3-й - регулярка-фильтр)
    2) У полученной функции-переменной (context) есть метод keys, который возвращает список всех найденных файлов (их имена).
    3) Для каждого найденного файла вызывается рекурсивно функция context, таким образом, все импорты в тестах разрешаются правильно.

    В итоге, ты можешь либо фильтровать вручную по ключам, либо передать в функцию require.context такие параметры, чтобы находился только 1 файл. А в самом файле подключать нужные спеки.
    Ответ написан
    Комментировать
  • Как соединить 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 комментариев
  • Как рендерить во view, дожидаясь загрузки данных по ajax в model?

    @bromzh
    Drugs-driven development
    Да, ты не понимаешь асинхронность в JS и MVC.
    Нужно рендерить после получения данных. Например, можно вызывать функцию render в колбеке getJSON. Ещё лучше вернуть промис и вызывать рендрер в колбеке then.
    Но это всё равно ни разу не MVC.
    А не могли бы вы помочь, как это делать в парадигме MVC?

    Ну тут всё не так просто. Если ты хочешь использовать MVC-фреймворки, то смотри, как там всё организовано у них. Примеры реализации простого MVC приложения см. тут.

    Если же забыть про тонны готовых MVC, то можно сделать всё самому. Тут важно понимать, что:
    1) Модель - это вся бизнес-логика. И она не знает ни про View, ни про Controller. В классическом MVC модель оповещает всех подписчиков об изменении своих данных.
    2) Вид (view) должен знать про модель, но не про контроллер. В классическом MVC вид подписывается на события модели и при возникновении события он перерисовывается.
    3) Контроллер знает про вид и про модель. В классическом MVC он связывается с каким-то видом и при определённом действии пользователя что-то делает. Например, он может вызывать какие-то методы у модели. А может и изменять состояния вида (хотя так лучше не делать в идеале, так как повысится связность системы, что плохо).

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

    Сперва посмотри в script.js.

    Там есть класс-модель. Чтобы связать Model и View обычно применяют паттерн проектирования observer. У модели есть список слушателей. Каждый слушатель - просто функция-коллбек, которая принимает 1 аргумент - данные этой модели. При этом, сама модель не знает вообще ни про какой View. Слушатели в модели - это просто массив функций, которые будут вызваны.
    В модели есть метод для добавления слушателя и для оповещения всех слушателей о получении новых данных. Метод getData эмулирует асинхронный запрос данных. В этом методе создаётся промис. Если данные найдены, то вызывается метод оповещения всех слушателей и промис резолвится. Если данные не найдены, то промис реджектится.

    Далее, небольшая иерархия view-классов.
    Класс BaseView. Там есть конструктор, который связывает экземпляр класса с DOM-элементом; метод subscribe, который добавляет к модели простого слушателя. Слушатель вызывает метод render с данными, которые нужно отрендерить и записывает полученный из метода render HTML в элемент. В самом классе BaseView метод render выплюнет ошибку, так что нужно написать несколько классов-наследников.
    Класс ListView наследуется от BaseView и просто добавляет вспомогательный метод, который просто обрамляет каждый объект из массива с данными в элемент .
    Ну и наконец, есть 2 класса, которые непосредственно реализуют метод render.
    В итоге, класс UlView генерирует из массива данных ненумерованный список, а класс OlView - нумерованный.

    Теперь в самом index.html можно увидеть всё в деле. Создаём модель и 2 view. Каждый view инициализируем соответствующим div-элементом. Далее,
    При нажатии на кнопку вызывается коллбек, который вызывает метод модели. Если модель смогла получить данные, то подписанные на эту модель вьюхи рендерят эти данные, причём каждый view делает это по-разному. Как тут можно заметить, модель вообще никак не зависит от view. Можно связывать сколько угодно вьюх без какого-либо изменения самой модели.

    В общем, как-то так. Это конечно очень простой и довольно корявый пример (например, тут нет возможности связать контроллер и сам view, это уж сам изучи), так что не следует этот код использовать где-то в своих проектах.
    Ну и почитай ещё про MVC, посмотри реализацию TodoMVC на разных фреймворках.
    Ответ написан
    4 комментария
  • Не появляется отображается в директиве информация, что делать?

    @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 = 'Заказ не найден';
            });
    }
    Ответ написан
    Комментировать
  • Связь данных между базами в MongoDB возможно ли?

    @bromzh
    Drugs-driven development
    Вот зачем брать NoSQL БД, а потом спрашивать, как тут делать типичные для реляционных баз вещи.
    Нужны связи - бери postgresql какой-нибудь. Или меняй схему и храни задачи вместе с пользователем в 1 документе. Зачем использовать инструмент не по назначению?

    Но если уж приспичило, то читай тут. Не знаю, есть ли join'ы на уровне БД в монге, но если чо, их можно сделать программно в 2 запроса.
    Ответ написан
    Комментировать
  • Webpack и Local CSS - как подружить?

    @bromzh
    Drugs-driven development
    лоадер css и styles в конфиге вебпака указал?
    Ответ написан
    4 комментария
  • Числа Фибоначчи в JS(рекурсия). Как работает функция?

    @bromzh
    Drugs-driven development
    Читай классику, хотя бы первые 2-3 главы, там разъясняют всё на пальцах.
    Ну и посмотри на страницы 47-69.
    Ответ написан
  • Реальные задачи по js?

    @bromzh
    Drugs-driven development
    Например, пусть напишет библиотеку для построения диаграмм Ганта, как тут. А то в последних обновлениях из бесплатной версии выпилили много хороших штук, а вменяемых аналогов нет.
    Ну и чтобы код и вёрстка были современные, а то там всё довольно печально.
    Ответ написан
    Комментировать
  • Как добавить 0 перед месяцем и днём?

    @bromzh
    Drugs-driven development
    Самое простое - подключить moment.js, потому что стандартные средства для работы с датами фиговые.
    Или использовать что-то типа этого.
    Ответ написан
    Комментировать