Ответы пользователя по тегу JavaScript
  • Стоит ли сейчас изучать Angular 1x?

    @bromzh
    Drugs-driven development
    Всё зависит от целей.

    Если есть желание поддерживать старые проекты, то да, изучать стоит. Первую версию пару лет разработчики ещё будут поддерживать. Вакансии пока есть, и их больше, чем по второму. Но со временем эти проекты либо перейдут на 2-ку, либо станут легаси-кодом, пилить который то ещё удовольствие. Ну а новые проекты нет причин начинать писать на 1-й ветке.
    Да, вакансий по второму ангуляру пока мало, но и сам фреймворк в стадии RC. Через полгода-год их заметно поприбавится.
    Ответ написан
  • Как открыть разные шаблоны в зависимости от параметра angular?

    @bromzh
    Drugs-driven development
    https://docs.angularjs.org/api/ng/directive/ngInclude

    Но это попахивает г-нокодом. Делай директиву, в неё передавай catid.
    Ответ написан
    Комментировать
  • Как вернуть значение из Promise у Javascript?

    @bromzh
    Drugs-driven development
    Никак. Промисы не делают код синхронным. Это просто более удобный способ организовать цепочку вызовов асинхронных функций. Получить и использовать значение можно только внутри колбеков (которые внутри then/catch).
    Ответ написан
    3 комментария
  • В одном nodejs модуле используется promise, но почему promise возвращает Promise { }?

    @bromzh
    Drugs-driven development
    Метод VK.call возвращает промис. Функция start возвращает результат выполнения VK.call.
    С чего вдруг он должен вернуть response?
    Ответ написан
    Комментировать
  • Как выполнить getElementById у результата getElementById?

    @bromzh
    Drugs-driven development
    А смысл? ID всё равно уникальный, зачем искать среди дочерних элементов. За ненадобностью, метод поиска по ID оставили только у document.
    Ответ написан
    4 комментария
  • Angular2. Как добавить класс блоку при mousehover?

    @bromzh
    Drugs-driven development
    А повестить обработчик можно только на весь компонент целиком? Хотелось бы на отедльный dom-элемент


    Ну так тоже просто: plnkr.co/edit/WaVyVLBI0B3zEo8vOnRL?p=preview
    @Component({
      selector: 'my-app',
      styles: [`
        .highlight { background: yellow; }
      `],
      template: `
        <h1 [class.highlight]="highlighted">My First Angular 2 App</h1>
        <div
          (mouseover)="onMouseOver()"
          (mouseout)="onMouseOut()">Hover me</div>
      `
    })
    export class AppComponent {
      highlighted: boolean;
      
      onMouseOver() {
        this.highlighted = true;
      }
      onMouseOut() {
        this.highlighted = false;
      }
    }
    Ответ написан
    Комментировать
  • Angular2. Как в роутере передать параметр в компонент (@Input)?

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

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

    @bromzh
    Drugs-driven development
    TypeScript, потому что angular2. Ну и TypeScript написан на TypeScript, ставится через npm, его легче понять/допилить чуть что. TS лучше поддерживается редакторами и IDE.
    Flow написано на окамле и не работает под виндой. А техническим решениям фейсбука я вообще не доверяю, там сплошь интересные личности от мира IT работают.
    Ответ написан
    Комментировать
  • Инджект сервиса в сервис в 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 комментария
  • Как реализовать кнопку/ссылку с таймером?

    @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";
      }
    }
    Ответ написан
    Комментировать
  • Как импортировать тесты с es6 модулями?

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

    В итоге, ты можешь либо фильтровать вручную по ключам, либо передать в функцию require.context такие параметры, чтобы находился только 1 файл. А в самом файле подключать нужные спеки.
    Ответ написан
    Комментировать
  • На чем лучше реализовывать таблицы для 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 = 'Заказ не найден';
            });
    }
    Ответ написан
    Комментировать
  • Webpack и Local CSS - как подружить?

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

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