diff --git a/hsp/rt/$root.js b/hsp/rt/$root.js
index fa5faea..6da52e5 100644
--- a/hsp/rt/$root.js
+++ b/hsp/rt/$root.js
@@ -33,8 +33,8 @@ var CPT_TYPES={
var DOCUMENT_FRAGMENT_NODE = 11;
/**
- * Root node - created at the root of each template
- * Contains the listeners requested by the child nodes
+ * Root node - created at the root of each template
+ * Contains the listeners requested by the child nodes
* Is replaced by the $CptNode (child class) when the template is inserted in another template
*/
var $RootNode = klass({
@@ -51,7 +51,7 @@ var $RootNode = klass({
* @param {Map} ctlInitAtts the init value of the controller attributes (optional) - e.g.
* {value:'123',mandatory:true}
*/
- $constructor : function (vscope, nodedefs, argnames, ctlWrapper, ctlInitAtts) {
+ $constructor : function(vscope, nodedefs, argnames, ctlWrapper, ctlInitAtts) {
if (this.isInsertNode) {
TNode.$constructor.call(this, this.exps);
} else {
@@ -125,12 +125,16 @@ var $RootNode = klass({
o.$dispose();
}
this.propObs=null;
+ this.$disposeCtlWrapper();
+ TNode.$dispose.call(this);
+ },
+
+ $disposeCtlWrapper: function() {
if (this.ctlWrapper) {
this.ctlWrapper.$dispose();
this.ctlWrapper = null;
this.controller = null;
}
- TNode.$dispose.call(this);
},
/**
@@ -318,6 +322,7 @@ var getObject = exports.getObject = function (path, scope) {
o = o[path[i]];
}
}
+
return o;
};
@@ -338,7 +343,7 @@ var $CptNode = klass({
* expression index associated to the event hanlder callback
* @param {Array} children list of child node generators - correponding to pseudo components and attribute content
*/
- $constructor : function (tplPath, exps, attcfg, ehcfg, children) {
+ $constructor : function(tplPath, exps, attcfg, ehcfg, children) {
this.pathInfo=tplPath.slice(1).join("."); // debugging info
this.info="[Component: #"+this.pathInfo+"]"; // debug info
this.isCptNode = true;
@@ -411,7 +416,7 @@ var $CptNode = klass({
ni.node2=node2;
if (p.cptType==="$CptAttInsert") {
- // this cpt is used to an insert another component passed as attribute
+ // this cpt is used to an insert another component passed as attribute
ni.initCpt(po);
} else {
// we are in a template or component cpt
@@ -425,7 +430,7 @@ var $CptNode = klass({
// create an element to avoid generating other errors
ni=this.createCptInstance("$CptAttInsert",parent);
}
-
+
return ni;
},
@@ -433,12 +438,12 @@ var $CptNode = klass({
* Calculates the object referenced by the path and the component type
* @return {Object} object with the following properties:
* pathObject: {Object} the object referenced by the path
- * cptType: {String} one of the following option: "$CptComponent",
+ * cptType: {String} one of the following option: "$CptComponent",
* "$CptTemplate", "$CptAttInsert" or "InvalidComponent"
*/
getPathData:function(path, vscope) {
- // determine the type of this component:
- // - either a template - e.g. <#mytemplate foo="bar"/>
+ // determine the type of this component:
+ // - either a template - e.g. <#mytemplate foo="bar"/>
// -> instance will extend $CptTemplate
// - a component with controller - e.g. <#mycpt foo="bar"/>
// -> instance will extend $CptComponent
@@ -513,7 +518,7 @@ var $CptNode = klass({
nd.appendChild(this.node2);
}
},
-
+
/**
* Callback called when a controller attribute or a template attribute has changed
*/
@@ -599,12 +604,21 @@ var $CptNode = klass({
if (tplChanged) {
// check if component nature changed from template to component or opposite
+
+ // Change might also be a different component ref, ie cpt1 -> cpt2
+ // let's dispose anything related to previous template
+ if (this.template.$dispose) {
+ this.template.$dispose(true);
+ } else {
+ // this.template might be only a reference to template closure function, not what it returns
+ this.$disposeCtlWrapper();
+ }
this.template=tpl;
this.createChildNodeInstances();
} else {
if (this.refreshAttributes) {
this.refreshAttributes();
- // for component and sub-templates the original vscope is substituted
+ // for component and sub-templates the original vscope is substituted
// to the one of the component- or sub-template
// so we need to revert to the parent scope to observe the correct objects
var vs=this.vscope;
@@ -668,7 +682,7 @@ var $CptNode = klass({
var sz=pos.length;
this._pathChgeCb = this.onPathChange.bind(this);
-
+
for (var i=0;sz>i;i++) {
json.observe(pos[i], this._pathChgeCb);
}
@@ -747,9 +761,9 @@ var $CptAttElement = klass({
isCptAttElement : true,
/**
- * $CptAttElement generator
+ * $CptAttElement generator
*/
- $constructor : function (name, exps, attcfg, ehcfg, children) {
+ $constructor : function(name, exps, attcfg, ehcfg, children) {
this.name = name;
this.info = "[Component attribute element: @"+this.name+"]";
this.tagName = "@"+name;
@@ -789,7 +803,7 @@ var $CptAttElement = klass({
if (p.ctlAttributes) {
attDef=p.ctlAttributes[this.name];
}
-
+
if (!eltDef && !attDef) {
// invalid elt
log.error(this.info+" Element not supported by its parent component");
@@ -846,4 +860,3 @@ cptComponent.setDependency("$CptAttElement",$CptAttElement);
exports.$RootNode = $RootNode;
exports.$CptNode = $CptNode;
exports.$CptAttElement = $CptAttElement;
-
diff --git a/hsp/rt/cptcomponent.js b/hsp/rt/cptcomponent.js
index 992babf..90cffee 100644
--- a/hsp/rt/cptcomponent.js
+++ b/hsp/rt/cptcomponent.js
@@ -138,11 +138,7 @@ exports.$CptComponent = {
* must be used when a new instance is created to adapt to a path change
*/
$dispose:function(localPropOnly) {
- if (this.ctlWrapper) {
- this.ctlWrapper.$dispose();
- this.ctlWrapper=null;
- this.controller=null;
- }
+ this.$disposeCtlWrapper();
this.ctlAttributes=null;
this.cleanObjectProperties(localPropOnly);
this.ctlConstuctor=null;
@@ -219,7 +215,7 @@ exports.$CptComponent = {
// nm is a template attribute passed as text attribute
if (this.tplAttributes && this.tplAttributes[nm]) {
// already defined: raise an error
-
+
log.error(this+" Component attribute '" + nm + "' is defined multiple times - please check");
} else {
// create new tpl Attribute Text Node and add it to the tplAttributes collection
diff --git a/test/rt/cptlifecyle.spec.hsp b/test/rt/cptlifecyle.spec.hsp
new file mode 100644
index 0000000..d18aa6d
--- /dev/null
+++ b/test/rt/cptlifecyle.spec.hsp
@@ -0,0 +1,99 @@
+
+
+
+ I am component 1
+
+
+
+ I am component 2
+
+
+
+ {if data.visible}
+ <#lifecycle1 />
+ {/if}
+
+
+
+ <#data.cpt />
+
+
+
+
+