From cf2889dd5a3afaa671b7a26fef0fb237925f8894 2014-12-03 19:30:05
From: Jason Grout <jgrout6@bloomberg.net>
Date: 2014-12-03 19:30:05
Subject: [PATCH] Make the model.views dict a dict of promises for views

Otherwise, there is a race condition where the model doesn't know about views until they are actually created.

---

diff --git a/IPython/html/static/widgets/js/manager.js b/IPython/html/static/widgets/js/manager.js
index c0f17fb..a368b4a 100644
--- a/IPython/html/static/widgets/js/manager.js
+++ b/IPython/html/static/widgets/js/manager.js
@@ -104,6 +104,7 @@ define([
                 return Promise.resolve(view.render()).then(function() {return view;});
             }).catch(utils.reject("Couldn't create a view for model id '" + String(model.id) + "'", true));
         });
+        model.views[utils.uuid()] = model.state_change;
         return model.state_change;
     };
 
diff --git a/IPython/html/static/widgets/js/widget.js b/IPython/html/static/widgets/js/widget.js
index 3336bce..e953aca 100644
--- a/IPython/html/static/widgets/js/widget.js
+++ b/IPython/html/static/widgets/js/widget.js
@@ -59,11 +59,12 @@ define(["widgets/js/manager",
             delete this.comm.model; // Delete ref so GC will collect widget model.
             delete this.comm;
             delete this.model_id; // Delete id from model so widget manager cleans up.
-            for (var id in this.views) {
-                if (this.views.hasOwnProperty(id)) {
-                    this.views[id].remove();
-                }
-            }
+            _.each(this.views, function(v, id, views) {
+                v.then(function(view) {
+                    view.remove();
+                    delete views[id];
+                });
+            });
         },
 
         _handle_comm_msg: function (msg) {
@@ -292,8 +293,6 @@ define(["widgets/js/manager",
             // Public constructor.
             this.model.on('change',this.update,this);
             this.options = parameters.options;
-            this.id = this.id || utils.uuid();
-            this.model.views[this.id] = this;
             this.on('displayed', function() { 
                 this.is_displayed = true; 
             }, this);