Angular updates direve VE and angulardirective based on the service status.

Source: Internet
Author: User
Tags emit

Angular updates direve VE and angulardirective based on the service status.

Angular JS (Angular. JS) is a set of frameworks, templates, and data binding and rich UI components used to develop web pages. It supports the entire development process and provides a web application architecture without manual DOM operations.

AngularJS is designed to overcome the shortcomings of HTML in building applications. HTML is a well-designed declarative language for static text display, but it seems weak to build WEB applications. AngularJS emerged here, making up for the natural defects of HTML and used for component Web applications.

TL; DR

This article explains three ways to update direve ve based on service status. They are the $ watch expression, event transmission, and the computing attribute of the controller.

Problem

I have a readerService that contains some status information (such as connection status and power consumption ). Now I need to make a direve ve to display these statuses. Because it only needs to get data from readerService and does not need to pass any external values, I directly inject the service into it. But how to update it becomes a problem.

The service Code is as follows.

const STATUS = {DETACH: 'DETACH',ATTACH: 'ATTACH',READY: 'READY'}class ReaderService {constructor() {this.STATUS = STATUS// The status will be changed by some callbacksthis.status = STATUS.DETACH}}angular.module('app').service('readerService', readerService)

The directive code is as follows:

angular.module('app').directive('readerIndicator', (readerService) => {const STATUS = readerService.STATUSconst STATUS_DISPLAY = {[STATUS.DETACH]: 'Disconnected',[STATUS.ATTACH]: 'Connecting...',[STATUS.READY]: 'Connected',}return {restrict: 'E',scope: {},template: `<div class="status">{{statusDisplay}}</div>`,link(scope) {// Set and change scope.statusDisplay here}}})

I have tried the following methods.

Method 1: $ watch

The first method is to use $ watch in directive to monitor readerService. status. Because it is not a property of directive scope, we need to wrap it with a function. Angular calculates and compares the old and new values during dirty-checking. Callback is triggered only when the status changes.

// In directivelink(scope) {scope.$watch(() => readerService.status, (status) => {scope.statusDisplay = STATUS_DISPLAY[status]})}

This method is simple and efficient. As long as the code that involves readerService. status changes triggers dirty-checking, directive will automatically update it. Service does not need to modify any code.

However, if multiple direve ve attributes are affected by service status, the $ watch code is obscure. Especially when the value modified by $ watch affects other values. For example:

// In directivelink(scope) {scope.$watch(() => readerService.status, (status) => {scope.statusDisplay = STATUS_DISPLAY[status]scope.showBattery = status !== STATUS.DETACH})scope.$watch('showBattery', () => {// some other things depend on showBattery})}

In this case, declarative programming style is easier to understand, such as computed property in Ember or Vue. This will be discussed later.

Method 2: $ broadcast/$ emit + $ on

This approach is to send an event every time the service status changes, and then listen to the event directive to change the status. Because status may have been updated during directive rendering. Therefore, we need to calculate an initial value in link.

I started with $ broadcast. The Code is as follows:

// In servicesetStatus(value) {this.status = value// Need to inject $rootScopethis.$rootScope.$broadcast('reader.statusChanged', this.status)}// In directivelink(scope) {scope.statusDisplay = STATUS_DISPLAY[nfcReaderService.status]scope.$on('reader.statusChanged', (event, status) => {scope.statusDisplay = STATUS_DISPLAY[status]})}

However, we immediately discovered that after $ broadcast, the UI update would always wait more than one second (but the $ on callback was very fast ). Google knows that $ broadcast broadcasts to all the lower-level scopes, and then dirty-checking after the broadcast is complete. A better way is to use $ emit, which only transmits events upwards, but $ rootScope is used no matter whether an event is sent or listened.

The modified code is as follows:

// In servicesetStatus(value) {this.status = value// Use $emit instead of $broadcastthis.$rootScope.$emit('reader.statusChanged', this.status)}// In directivelink(scope) {scope.statusDisplay = STATUS_DISPLAY[nfcReaderService.status]// Use $rootScope instead of scope$rootScope.$on('reader.statusChanged', (event, status) => {scope.statusDisplay = STATUS_DISPLAY[status]})}

If you have to use $ broadcast for some reason, you can force dirty-checking to be triggered by $ digest or $ apply at the end of the $ on callback, which can also achieve the goal of fast UI update.

Method 3: controller + property

I personally think the first two methods can solve the problem, but the code is not very easy to maintain. $ Watch is hard to understand when attributes are correlated. $ emit/$ on needs to write some logic twice (during direve ve initialization and callback execution ). Method 1 I mentioned that declarative attributes are easier to understand than $ watch. This method uses controller. Directive can set its own controller as the data source (or view model). We can use the attributes to be calculated as the controller attributes. In this way, dirty-checking is automatically calculated.

// In directiveclass ReaderController {constructor($scope, readerService) {this.readerService = readerService}get statusDisplay() {return STATUS_DISPLAY[this.readerService.status]}}return {// ...controller: ReaderController,controllerAs: 'vm',template: `<div class="status">{{vm.statusDisplay}}</div>}

In this way, most logics can be moved to the controller. If there is no DOM operation, we can not even write the link method. There is no need to add additional $ watch and $ on. Because of the dirty-checking feature, attributes bound to the template are usually calculated several times. Therefore, attributes must be very simple. In most cases, this is not a problem.

The above content is a small series of Angular updates direve ve based on the service status, I hope to help you!

Articles you may be interested in:
  • AngularJS directive returned Object Attributes
  • AngularJS Getting Started: direve VE and controller communication process
  • Directive in AngularJS implements delayed Loading
  • Define a table in Directive in AngularJS

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.