AngularJS. Наследование контроллеров и двухстороннее связывание данных


Содержание материала:

AngularJS Двухстороннее связывание данных

В моем контроллере у меня есть следующие данные:

Где-то в этом контроллере у меня есть функция, которая сначала получает данные из бэкэнда, а затем вызывает showModal :

Модальный контроллер выглядит так:

и в модальном контроллере есть такой метод:

Если я сделаю это так:

userManagement = data; и userManagementSomeDataObjects = data.someDataObjects; чем новые данные не установлены.

Если я устанавливаю каждое свойство отдельно от объектов, то оно работает чаще, чем нет, но иногда это не так.

Мой вопрос сейчас будет о том, что я могу сделать, чтобы заставить его работать. В настоящее время у меня нет $ scope-variable в моем модале, и на самом деле я не знаю, поможет ли $ scopeOfModal. $ Apply () , и я также не знаю, как получить доступ от модального к MyController — $ scope .

Буду рад любым подсказкам в этом направлении.

[РЕДАКТИРОВАТЬ] Вот изображение моего в данный момент просматриваемого (справа) и слева объекта, которое должно быть показано после установки в модал-функции.

есть ли возможность передать параметры этой функции в модальный контроллер:

Для меня это выглядит так, как будто это не имеет ничего общего с angular, просто некоторая путаница с ссылками на переменные javascript.

Сначала вы передаете userManagement из showModalService.showModal в ModalController посредством resolve .

Так что теперь ModalController имеет ссылку на тот же объект, что и showModalService .

Однако в ModalController вы переназначаете переменную userManagement чтобы вместо этого указывать на data . Так что теперь переменная userManagement внутри ModalController больше не указывает на ModalController объект, потому что вы переназначили его. Это не имеет ничего общего с угловым двусторонним связыванием данных, это просто назначение переменных javascript. Вы потеряли свою ссылку на оригинальный объект.

showModalService прежнему есть ссылка на экземпляр, который он отправил через resol, он не знает, что вы обменяли ссылку в ModalController .

Я бы попытался отправить объект, инкапсулирующий данные, которыми вы хотите поделиться, чтобы решить эту проблему.

Затем манипулируйте свойствами общего объекта вместо перезаписи ссылок.

Stepan Suvorov Blog

Release 2.0

Передача данных между сущностями AngularJS

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

Для начала определимся какими типами сущностей будем оперировать: это будет контроллер, сервис и представление.

Из контроллера в представление

Посредством $scope

либо для нового синтаксиса контроллера через this в контроллере:

а в шаблоне представления получим через переменную:

для нового синтаксиса:

Из представления в контроллер

Для этого мы используем two-way data binding с помощью директив ng-bind и ng-model в представлении:

теперь при изменении значения поля ввода будет изменяться name.first значение в контроллере.

Из представления в представление

Фактически осуществляется посредством контроллера (рассмотрено выше), но переменную-свойство в контроллере можем не создавать: она будет создана автоматически. Итого имеем связь представление – контроллер – представление. Важно, чтобы 2 элемента представления, которые собираемся синхронизировать, находились в рамках одного контроллера.

Из контроллера в сервис

тут все просто: инжектим сервис в контроллер и задаем значение свойству, либо вызываем сеттер-метод (что ИМХО более верно):

Из сервиса в контроллер

Мы не можем изменять данные контроллера в сервисе, но мы можем “залинковать” объект-свойство сервиса на свойство контроллера, тогда в случае изменений внутри этого объекта – данные контроллера также будут обновлены:

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

Из сервиса в представление

Осуществляется посредствам контроллера, то есть сервис – контроллер – представление.

и представление соответственно:

Из представления в сервис


Аналогично предыдущему: представление – контроллер – сервис.

Из сервиса в сервис

Один сервис инжектит другой и там вызывается сеттер-метод:

Из контроллера в контроллер

Самый интересный случай, когда в зависимости от специфики может быть решен различными способами. Возможные варианты:

  • из родительского контроллера в дочерний
  • и дочернего в родительский
  • из контроллера в контроллер, когда оба находятся на одном уровне (либо в разных ветках иерархии)

Рассмотрим каждый отдельно.

Из родительского контроллера в дочерний

тут также могут быть 2 случая:

  • открытый scope дочернего контроллера
  • изолированный scope дочернего контроллера

В случае с открытым – все просто: дочерний контроллер наследует свойства scope родителя по умолчанию:

– как видим nameController является дочерним по отношению к userController, поэтому мы легко можем получить доступ к свойствам родителя:

С случае с изолированным scope(который мы можем получить при создании директивы) нам необходимо “залинковать” необходимые свойства родительского в дочерний. Представление будет выглядеть следующим образом:

а код директивы и контроллера:

В этом месте мы описываем связывание:

– это означает, что name будет взято из атрибута директивы.

Из дочернего контроллера в родительский

Вот этот вариант уже поинтереснее, тут не все так просто, ибо не смотря на то, что мы можем получить доступ к свойствам scope родителя, этот доступ будет только на чтение. При попытке изменить какое-либо свойство родителя, мы лишь получим создание одноименного свойства в дочернем контроллере. Это объясняется прототипной моделью наследования scope.

Топ-пост этого месяца:  AngularJS. Внедрение зависимости (Dependency injection)

Возможны 2 решения:

  • изменяя не само свойство, а свойство свойства (знаю, сильно запутано, но на примере не должно быть сложно) То есть, вместо $scope.name, используем $scope.name.first.
  • через специально созданный сеттер-метод в родительском котроллере. Пример. :

Случай с изолированным скоупом полностью аналогичен предыдущему (Из родительского контроллера в дочерний), только линковка будет делаться не односторонняя:

Передача данных между контроллерами находящимися на разных ветках

т.е., грубо говоря, когда мы не можем применить к ним характеристику родитель-ребенок. Решение будет заключаться в нахождении общего родительского контроллера( вплоть до $rootScope ), посредством которого и будет осуществлена передача: контроллер А – общий родительский контроллер – контроллер Б.

Передача данных дочернего и родительского контроллера уже рассмотрена выше, поэтому даю просто общий пример связки (контроллерА – родительский контроллер – контроллерБ)

Также передача данных между несвязанными напрямую контроллерами может происходить с помощью событий.

Общение контроллеров с помощью событий

Это на столько отдельный случай, что я решил посвятить ему целый пункт.

Сразу оговорюсь: если вы еще только начинаете работать с AngularJS – не используйте этот подход . При неумелом его использовании может получиться такой “салат” из зависимостей, что потом сами не разберетесь.

Передавать события (с данными) можно посредством двух методов $scope.$emit и $scope.$broadcast. Отличие $emit от $broadcast заключается в том, что $emit передает события вверх по цепочке в скоупы всех родительских контроллеров, а $broadcast наоборот – в дочерние:

Чтобы словить событие необходимо использовать метод $scope.$on.

Полный пример работы с событиями.

Общение контроллеров с помощью специального сервиса

Существует еще один способ общения между сервисами, который напомнил Владимир Гомонов ( благодарю за дополнение! ), – это использование специального сервиса, который будет инжектиться в оба контроллера и в итоге получим связку: контроллер А – сервис – контроллер Б. Взаимодействие контроллер – сервис и сервис – контроллер уже рассмотрено выше, поэтому только выложу общий пример.

Вроде бы все возможные варианты передачи данных в рамках AngularJS перечислил, если что-то забыл – пишите – добавим.

AngularJS Двустороннее связывание данных между контроллером и сервисом — angularjs

У меня есть служба в угловой JS, которая определяется следующим образом:

Эта служба вызывает конечную точку для получения некоторых данных, я вызываю этот метод в функции запуска основного модуля, как показано ниже:

В моем контроллере у меня есть переменная с именем balance, в которой я хочу сохранить значение, полученное из службы, как показано в приведенном ниже коде:

Данные из службы возвращаются после того, как объект данных контроллера был настроен, и поэтому поле баланса не заполняется. Если я использую метод $ scope.watch, который закомментирован, тогда объект данных заполняется должным образом. Однако я был в предположении, что это не нужно делать, поскольку между службой и контроллером существует двухсторонняя привязка данных. Любая помощь приветствуется. Благодаря !


    1 2
  • 27 июл 2020 2020-07-27 04:20:19
  • kushaldsouza

2 ответа

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

КОД

Надеюсь, это поможет вам, спасибо.

  • 27 июл 2020 2020-07-27 04:20:20
  • Pankaj Parkar

Функция .run не перестает ждать, пока getAccountDetails вернет значение. Итак, когда вы назначаете this.data.balance = Account.accountDetails.balance , вы по существу делаете это: this.data.balance = undefined .

Согласно вышеприведенному комментарию, типичным способом является getAccountDetails() чтобы вернуть обещание, например:

AngularJS Связывание данных

Связывание данных в AngularJS является синхронизация между моделью и представлением.

Модель данных

AngularJS приложения обычно имеют модели данных. Модель данных представляет собой набор данных, доступных для применения.

пример

HTML Посмотреть

HTML контейнер, в котором отображается приложение AngularJS, называется вид.

Вид имеет доступ к модели, и есть несколько способов отображения данных модели в представлении.

Вы можете использовать ng-bind директиву, которая будет связывать innerHTML элемента к указанной модели собственности:

пример

Вы можете также использовать двойные фигурные скобки >> >> >> Для отображения контента из модели:

пример

Или вы можете использовать ng-model директивы на HTML управления для привязки модели к представлению.

ng-model Директива

Используйте ng-model директиву , чтобы связать данные из модели с точки зрения управления на HTML (ввод, выберите текстовое поле)

пример

ng-model директива обеспечивает двустороннюю связывания между моделью и представлением.

Двусторонний Binding

Связывание данных в AngularJS является синхронизация между моделью и представлением.

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

пример

AngularJS контроллер

Приложения в AngularJS управляются контроллерами. Читайте о контроллеров в AngularJS Контроллеры главы.

Из-за непосредственной синхронизации модели и представления, контроллер может быть полностью отделена от точки зрения, и просто сосредоточиться на данных модели. Благодаря привязке данных в AngularJS, вид будет отражать любые изменения, сделанные в контроллере.

Двухстороннее связывание данных AngularJS во вложенных директивах

Пожалуйста, дайте мне знать, если вам нужна дополнительная информация или вы хотите, чтобы я что-то разъяснил. Я пробовал много разных вещей, чтобы понять это, но не нашел решения.

Я относительно новичок в angularJS и пытаюсь создать приложение с несколькими слоями данных. У меня есть некоторая основная пользовательская информация, хранящаяся в области видимости тела на контроллере PageController. Затем у меня есть форма настроек, которая загружается с использованием $ routeParams (с контроллером SettingsController), которая включает пару пользовательских директив для шаблонных целей. Поскольку директивы вложены, я использую transclusion для загрузки второй внутри первой. Кажется, все это работает хорошо.


Моя проблема в том, что я пытаюсь сослаться на поле user.firstname из самой внутренней директивы и хочу использовать двустороннюю привязку данных, чтобы изменения, внесенные в текстовое поле, приводили к изменению значения в области видимости PageController. Я знаю, что многие проблемы такого рода вызваны использованием примитивов в ng-модели, но я попытался поместить все в дополнительный объект, чтобы бесполезно вызывать наследование прототипов. Что я здесь не так делаю?

Топ-пост этого месяца:  Как установить социальные кнопки для сайта WordPress

Вот код JSFiddle моего кода, максимально урезанный, чтобы изолировать проблему. В этом примере, если я введу внешнее текстовое поле, которое находится непосредственно в области действия PageController, оно будет изменять внутреннее текстовое поле до тех пор, пока не будет изменено это текстовое поле, при котором соединение разрывается. Это похоже на проблему использования примитивов, как описано в других вопросах, но я не могу понять, где проблема здесь.

# 3 Обмен данными между контроллерами в AngularJS

Всем привет. Сегодня мы с вами разберем как шарить данные между двумя контроллерами. Вот тестовый пример, где у нас есть два контроллера: firstCtrl с моделью hello и secondCtrl с моделю hello. Выглядит это вот так

Как мы видим, они никак не связаны и это два абсолютно разных скоупа, в которых описаны переменные hello. И мы хотим как-то сделать так, чтобы данные обновлялись одновременно в обоих контроллерах. Очень часто, когда вы делаете какое-то приложение, у вас возникает проблема, когда данные одни и те же и нужно, чтобы они были одинаковые в обоих контроллерах, например.

В Angular для этого используется такая вещь как фабрика и сегодня мы разберем что это такое.

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

Так же, как мы описывали контроллер, описываем factory.

Фабрика обязательно должна что-то возвращать. В данном случае будем возвращать обьект, у которого будет одно проперти hello и оно будет равняться hello world.

Еще раз. Мы описываем фабрику, это функция, которая возвращает обьект. У нее есть проперти hello, которое равняется hello world. Дальше мы можем эту фабрику использовать в любом контроллере.

Для того, чтобы ее использовать, ее нужно сначала подмешать. Здесь же, где мы подмешали $scope — мы передаем myFactory и теперь эта фабрика будет доступна внутри контроллера.

Теперь давайте напишем в контроллере $scope.myFactory = myFactory;

Зачем мы это делаем? Сейчас myFactory недоступна внутри шаблона. Она доступна только в контроллере. Если мы хотим, чтобы переменная была доступна внутри шаблона, то мы должны ее занести в $scope. Тоже самое сделаем во втором контроллере.

Что это нам дает? Теперь, например, в нашем шаблоне мы можем заменить ng-model=»hello» на ng-model=»myFactory.hello» так как мы знаем, что myFactory нам уже достуна в шаблоне. И тоже самое во втором случае.

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

Как мы видим, теперь данные обновляются одновременно. Это именно то, чего мы добивались. Теперь если мы хотим шарить между двумя контроллерами какие-то данные, мы можем просто добавлять их в myFactory и использовать их как в первом, так и во втором контроллере.

AngularJS Двухсторонняя привязка данных перестает работать

пример

Следует иметь в виду, что:

  1. Угловое связывание данных основывается на прототипном наследовании JavaScript, поэтому оно подвержено переменному затенению .
  2. Дочерняя область, обычно прототипически наследуемая от своей родительской области. Единственное исключение из этого правила — это директива, которая имеет изолированную область действия, поскольку она не прототипически наследуется.
  3. Существуют некоторые директивы, которые создают новую дочернюю область: ng-repeat , ng-switch , ng-view , ng-if , ng-controller , ng-include и т. Д.

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

Эту проблему можно легко избежать, выполнив следующие шаги:

  1. Имейте «.» внутри вашего HTML-шаблона всякий раз, когда вы связываете некоторые данные
  2. Используйте синтаксис controllerAs поскольку он способствует использованию привязки к «пунктируемому» объекту
  3. $ parent может использоваться для доступа к переменным родительской scope а не к области содержимого. как внутри ng-if мы можем использовать ng-model=»$parent.foo» ..

Альтернативой для этого является привязка ngModel к функции getter / setter, которая будет обновлять кэшированную версию модели при вызове с аргументами или возвращать ее при вызове без аргументов. Чтобы использовать функцию getter / setter, вам нужно добавить ng-model-options=»< getterSetter: true >» к элементу с атрибутом ngModal и вызвать функцию getter, если вы хотите отобразить ее значение в выражении ( Рабочий пример ).

пример

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

Связывание данных в AngularJS

В этом разделе мы увидим, как мы можем легко обновлять наши представления с помощью ngModel. Прежде всего, согласно приложениям Angular, связывание данных — это автоматическая синхронизация данных между моделью и представлением (для тех, кто не в курсе всего этого вообще, пожалуйста, взгляните на шаблон MVC).

Что касается реализации в Angular, представление является проекцией модели во времени. При изменении модели изменения отражаются в представлении, и наоборот.

В целях лучшего понимания упомянутого связывания данных или сравнения классических систем шаблонов с Angular, пожалуйста, обратитесь к официальной документации.

Вступление

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

Что вам нужно знать

Шаблоны

В Angular шаблоны написаны на HTML, который содержит специфичные для Angular элементы и атрибуты. Angular комбинирует шаблон с информацией от модели и контроллера для отображения динамического представления, который пользователь видит в браузере.

Вы можете использовать следующие элементы и атрибуты Angular:

  • Директива — атрибут или элемент, который дополняет существующий элемент в DOM или представляет собой повторно используемый компонент DOM.
  • Разметка — двойные фигурные скобки <<>>, чтобы привязать выражения к элементам.
  • Фильтр — форматы данных для отображения.
  • Элементы форм — проверяет пользовательский ввод.

Для получения более подробной информации о шаблонах Angular, пожалуйста, обратитесь к официальной документации.

Топ-пост этого месяца:  Взаимодействие Vue js TypeScript преимущества и примеры разработки проектов

ngModel


Директива ngModel связывает , ,

(или произвольный элемент формы) со свойством в $scope с помощью NgModelController, который создаётся и обрабатывается этой директивой.

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

Прежде, чем погрузиться в исходный код этого примера, важно знать, что ngModel попытается привязаться к свойству, предоставленному путём оценки выражения в текущем $scope . Это означает, что если свойство в $scope не существует, оно будет создано неявно и добавлено в $scope .

Пример

Одного файла достаточно!

Во-первых, очевидно, мы должны определить, что это приложение Angular (строка 2). Во-вторых, мы создаём вид таблицы исходя из наших потребностей: две строки (имя и фамилия), в каждой по две колонки (с соответствующим текстовым полем для имени и фамилии). Наконец, мы показываем наше сообщение в строке 20.

Весь процесс основан на присваиваемых переменных в ng-model . Таким образом, это работает как вложенный контроллер, связывающий данные с нашим представлением. Этот вид данных может быть получен/показан с помощью фигурных скобок в разметке Angular.

Как правило, тег , когда применяется совместно с ng-model, обеспечивает привязку данных, управление состоянием и проверку.

Демонстрация

Сперва, пожалуйста, взгляните на этот пост, просто чтобы понять, почему вы должны развернуть это приложение на локальном сервере, а не просто выполнить его в браузере. Доступ к веб-приложение с локального сервера:

Директивы AngularJS 1.4: область действия, двухстороннее связывание и bindToController

Обновление. Должно быть, это было что-то глупое в другой части кода. Теперь он работает, поэтому синтаксис bindToController прекрасен.

Мы используем AngularJS 1.4, который ввел директиву новый способ использования bindToController.

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

Вызов из другого вида:

Ранее определенный в контроллере представления:

Ссылка на переменные в шаблоне директивы следующим образом:

Мы потратили 4 часа, пытаясь понять, почему наша директива не работает. Ну, он работал, но двухсторонняя привязка между контроллером и директивой не была, vm.address.street был безнадежно установлен на нуль.

Через некоторое время мы просто попробовали старый способ:

И это волшебно сработало. Любая идея ПОЧЕМУ?

1 ответ

Update:

Благодаря ссылке на это сообщение в блоге мне нужно обновить свой ответ. Поскольку AngularJS 1.4 действительно кажется, что вы можете использовать

который будет делать (точную) ту же самую вещь, что и старый синтаксис:

Полезные строки исходного кода AngularJS для объяснения этого поведения:

Оригинальный ответ:

Надеюсь, я могу объяснить вам, почему это поведение вы испытали правильно и где вы пропустили понимание концепции привязки сферы.

Позвольте мне объяснить, что вы сделали в своем первом фрагменте кода:

С помощью scope: <> вы создали изолированную область (без какого-либо наследования) для вашей директивы mdAddress . Это означает: данные не передаются между родительским контроллером и вашей директивой.

Имея это в виду, относительно второго фрагмента кода:

vm.address из вашего родительского контроллера/представления будет назначаться как выражение для атрибута адреса директивы, но поскольку вы ранее определяли изолированную область, данные не передаются в AddressController и, следовательно, недоступны в bindToController .

Давайте рассмотрим определение объекта scope как «какие данные будут переданы» и bindToController как «какие данные будут доступны в моем объекте controllerAs как объект».

Итак, теперь давайте посмотрим на последний (и фрагмент рабочего кода):

Здесь вы создали изолированную область, но на этот раз вы добавили атрибут address , который будет передан как выражение. Итак, теперь address , который вы передали из представления во втором фрагменте, будет доступен в области контроллера. Теперь установка bindToController: true свяжет все текущие свойства области с контроллером (или, скорее, объект controllerAs). И теперь это работает так, как вы ожидаете, потому что данные будут переданы в область и данные будут переданы в область шаблонов контроллера.

Этот краткий обзор поможет вам лучше понять концепцию объектов определения scope и bindToController ?

Двусторонний data binding в AngularJS

В этом уроке я покажу, как работает двустороннее связывание в AngularJS на примере конструктора визитных карточек. Этот конструктор позволит создавать виртуальные визитные карточки, которые можно персонализировать, указав имя, род занятий, адрес электронной почты, логотип компании, а также ссылки на домашнюю страницу и профили в социальных сетях. Также можно будет настроить фон, цвет текста, используя элементы HTML5, и сразу посмотреть все изменения на экране.

В итоге мы должны получить следующее:

Подготовка

Мы будем использовать Bower для управлять зависимостями в проекте. Bower является менеджером пакетов, его можно установить через npm (для этого должен быть установлен Node.js). Об установке Node.js (или npm) можно почитать в статье . Подробнее об установке Bower вы можете прочитать в документации к нему .

Зависимостями в нашем проекте будут Bootstrap Framework (для стилизации), Font Awesome (для иконок), jQuery (зависимость Bootstrap) и AngularJS.

Если у вас установлен и настроен Bower, создайте новый каталог, перейдите в этот каталог и инициализируйте проект с помощью Bower:

В корневой директории проекта будет создан файл bower.json. Bower задаст несколько вопросов, например, название проекта, имя автора, описание и т.д. Введите название «ACG» (Angular Card Generator) и заполните остальные поля по своему усмотрению (можно оставить значения по умолчанию). В результате bower.json должен выглядеть так:

Далее выполните следующие команды в терминале:

Эти команды установят зависимости в директорию bower_components и сохранят их в bower.json. Также полезно добавить папку bower_components в .gitignore, чтобы не загружать эту папку в репозиторий. Любой контрибьютор сможет установить зависимости, выполнив команду bower install.

Анатомия проекта AngularJS

В корневой директории проекта создайте файлы index.html и style.css. Добавьте следующий код в index.html:

Мы добавили директивы ng-app=»myApp» и ng-controller=»BusinessCardController»; тегу . Директива ng-app сообщает Angular, что вся страница является приложением AngularJS, а директива ng-controller связывает контроллер с представлением.

В title мы использовали директиву ng-bind, которая связывает заголовок страницы с моделью, а также подключили необходимые css (в ) и js файлы (перед закрывающимся тегом

Добавить комментарий