HOW-TO Initialize Dart WebComponent

130 views Asked by At

I have a Dart WebComponent that obtains information periodically from a web service. I'd like to inject the web service into the component and have the component decide when to call the web service (this will allow me to prototype all the UI code using a mock web service with no HTTP call until the service is written).

The issue I'm having is that the web service object I'm sending to the WebComponent seems to be null until the page is rendered. I'm not exactly sure when the service reference is passed to the page, but it seems to happen after the page is constructed since the value is null in the WebComponent constructor, but I can see that the value is instantiated when the page itself is rendered. How can I be notified that the service object is now available to the page so I can call the web service?

Follow up question: Is passing the service reference into the WebComponent like I am below a bad practice? If so, what should I do instead to separate the mock implementation so I can inject the real web service later without changing any code.

Here's my base Dart page:

<!DOCTYPE html>

<html>
  <head>
    <meta charset="utf-8">
    <title>Dart Prototype</title>
    <link rel="stylesheet" href="dart_prototype.css">

    <link rel="import" href="location_container.html">
  </head>
  <body>
    <h1>Dart Prototype</h1>

    <div id="location_management_container">
        <location-container location-service="{{applicationContext.locationService}}" count="{{startingCount}}"></location-container>
    </div>

    <script type="application/dart">
      import 'package:web_ui/web_ui.dart';
      import 'package:dart_prototype/dart_prototype_library.dart';

      final ApplicationContext applicationContext = new ApplicationContext(
        new WebService()
      );
      int startingCount = 5;

      main() {
        print('main initializing');
        print(applicationContext);
        print(applicationContext.locationService);
      }      
    </script>
    <script src="packages/browser/dart.js"></script>
  </body>
</html>

Here's the code for location-container

<!DOCTYPE html>

<html>
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <element name="location-container">
      <template>
        <div>
          <ul id="todo-list">
            <li>hi there!</li>
            <li>{{count}}</li>
            <li>{{locationService}}</li>
          </ul>        
        </div>
      </template>
      <script type="application/dart">
        import 'package:web_ui/web_ui.dart';
        import 'package:dart_prototype/dart_prototype_library.dart';

        class LocationContainer extends WebComponent {

          @observable
          WebService locationService;

          @observable
          int count;  

          LocationContainer() {  
            print('in loc container constructor');
            print(locationService);
            print(count);
          }      

          created() {
            print('created!');
            print(locationService);
            print(count);
          }              
        }        
      </script>
    </element>
  </body>
</html>

Here's the code for ApplicationContext and WebService

part of prototype_library;

class ApplicationContext {

  final WebService locationService;

  ApplicationContext(
      this.locationService);

}

class WebService {

  final Factory _objectFactory;

  WebService(this._objectFactory);

  Future call(String url) {
    throw new UnimplementedError();
  }
}

And here's the result of my print strings statements to the console

Invalid CSS property name: -webkit-touch-callout
main initializing
Instance of 'ApplicationContext'
Instance of 'WebService'
in loc container constructor
null
null
created!
null
null

And here's what my rendered page returns:

Dart Prototype

 - hi there!
 - 5 
 - Instance of 'WebService'

And the source of that page...

<!DOCTYPE html>
<!-- This file was auto-generated from web/dart_prototype.html. -->
<html><head><style>template { display: none; }</style>
    <meta charset="utf-8">
    <title>Dart Prototype</title>
    <link rel="stylesheet" href="../dart_prototype.css">


  </head>
  <body>
    <h1>Dart Prototype</h1>

    <div id="location_management_container">
        <span is="location-container"></span>
    </div>


    <script type="application/dart" src="dart_prototype.html_bootstrap.dart"></script><script src="../packages/browser/dart.js"></script>


</body></html>
1

There are 1 answers

0
Vinnie On

I think my problem may be solved by using the inserted life cycle method instead of created.

Initially when I read the WebComponent life cycle method description, it said:

Invoked whenever a component is added to the DOM.

I'm still not sure if this is the right method to use, but I have the object I'm looking for - so I'm going to continue to experiment. Here's my updated WebComponent

<!DOCTYPE html>

<html>
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <element name="location-container">
      <template>
        <div>
          <ul id="todo-list">
            <li>hi there!</li>
            <li>{{count}}</li>
            <li>{{locationService}}</li>
          </ul>        
        </div>
      </template>
      <script type="application/dart">
        import 'package:web_ui/web_ui.dart';
        import 'package:dart_prototype/dart_prototype_library.dart';

        class LocationContainer extends WebComponent {

          @observable
          WebService locationService;

          @observable
          int count;  

          LocationContainer() {  
            print('in loc container constructor');
            print(locationService);
            print(count);
          }      

          created() {
            print('created!');
            print(locationService);
            print(count);
          }

          inserted() {
            print('inserted!');
            print(locationService);
            print(count);
          }

        }        
      </script>
    </element>
  </body>
</html>