2
votes

I have a Dart app in which I need to set a number of fields based on what's coming back from a JSON request. I'm extending PolymerElement and using @observable to keep the field in sync. What I want to be able to do is to set a global variable and have that drive the class level variable. I'm sure I'm missing something fundamental, but I can't access the object that's being used by the HTML because it hasn't been instantiated (or has it?).

mobilemenu.dart

library mobilemenu;

import 'dart:html';
import 'order_item.dart' as orderitem;

main() {}

mobilemenu.html

<!DOCTYPE html>
<html>
    <head>
        <link rel="import" href="order_item.html">
        <script src="packages/polymer/boot.js"></script>
    </head>
    <body>
        <div class="mobile-menu-product-name">
            <order-item></order-item>
        </div>
    </body>
</html>

order_item.dart

library orderitem;

import 'package:polymer/polymer.dart';
import 'dart:html';
import 'dart:json' as JSON;

@observable String g_product_name;

@CustomTag('order-item')
class OrderItem extends PolymerElement with ObservableMixin {
  @observable String product_name = g_product_name;
}

Map processString(String jsonString) {
  // Create a map from json string
  Map jsonParse = JSON.parse(jsonString);
  print(jsonParse);
  return jsonParse;
}

setGlobals(Map jsonMap) {
  g_product_name = jsonMap["details"][0]["product_name"];
  print(g_product_name);
}

main() {

  var baseUrl = "https://example.com/add_item.json";
  var params = window.location.search;
  var fullUrl = baseUrl + params;

  HttpRequest.getString(fullUrl)
    .then(processString)
    .then(setGlobals);

}

order_item.html

<polymer-element name="order-item">
  <template>
    <div>
      <span>{{product_name}}</span>
    </div>
  </template>
  <script type="application/dart" src="order_item.dart"></script>
</polymer-element>
1

1 Answers

0
votes

Edit--Working Example

Your real issue is that

@observable String product_name = g_product_name;

doesn't set product_name to g_product_name, it sets product_name to the value of g_product_name at the time of assignment, which is null. Changing the value of g_product_name does not change the value of product_name.

I got around it by making a container for your global variable and making the property observable. That way you can set OrderItem property to the same object that your global variable is set to and it will bind the template to the property in your global variable.

add_item.json

{"details": [{"product_name": "foobar"}]}

order_item.html

<!DOCTYPE html>
<html>
    <head>
        <link rel="import" href="order_item.html">
        <script src="packages/polymer/boot.js"></script>
    </head>
    <body>
        <div class="mobile-menu-product-name">
            <order-item></order-item>
        </div>
    </body>
</html>

order_item.dart

library orderitem;

import 'package:polymer/polymer.dart';
import 'dart:html';
import 'dart:json' as JSON;

class GlobalVariable extends ObservableBase {
  @observable
  String g_product_name;
}
GlobalVariable globalVariable = new GlobalVariable();

@CustomTag('order-item')
class OrderItem extends PolymerElement with ObservableMixin {
  GlobalVariable _globalVariable = globalVariable;
}

Map processString(String jsonString) {
  // Create a map from json string
  Map jsonParse = JSON.parse(jsonString);
  print(jsonParse);
  return jsonParse;
}

setGlobals(Map jsonMap) {
  globalVariable.g_product_name = jsonMap["details"][0]["product_name"];
  print(globalVariable.g_product_name);
}

main() {

  HttpRequest.getString("add_item.json")
    .then(processString)
    .then(setGlobals);

}

It works for me. I replaced your main in order_item.dart with the following and it updated the order item to foobar.

main() {
  setGlobals({"details":
    [
      {
        "product_name": "foobar"
      }
    ]
  });
}

Obviously example.org/add_item.json isn't a working url, so I'd check to make sure the url is returning what you expect and the json structure is correct. Otherwise, it should work.