From 1bc334f8078e6449f4cf3efe008c266b0a74001b Mon Sep 17 00:00:00 2001 From: fbernardo Date: Wed, 22 Jan 2014 11:18:49 +0100 Subject: [PATCH] feat #921 aria:List widget refresh on datamodel change Now when you use aria.utils.Json.add and aria.utils.Json.removeAt functions to add items to an aria:List widget (or to remove one), the list template is refreshed and it displays the new item. --- src/aria/widgetLibs/BindableWidget.js | 50 +++++------ src/aria/widgets/form/list/List.js | 50 +++++++++++ test/aria/widgets/form/FormTestSuite.js | 2 +- .../form/{ => list}/ListControllerTest.js | 2 +- test/aria/widgets/form/list/ListTestCase.js | 83 +++++++++++++++++++ .../widgets/form/list/ListTestCaseTpl.tpl | 40 +++++++++ test/aria/widgets/form/list/ListTestSuite.js | 24 ++++++ 7 files changed, 225 insertions(+), 26 deletions(-) rename test/aria/widgets/form/{ => list}/ListControllerTest.js (99%) create mode 100644 test/aria/widgets/form/list/ListTestCase.js create mode 100644 test/aria/widgets/form/list/ListTestCaseTpl.tpl create mode 100644 test/aria/widgets/form/list/ListTestSuite.js diff --git a/src/aria/widgetLibs/BindableWidget.js b/src/aria/widgetLibs/BindableWidget.js index 1c5489074..26361c19b 100644 --- a/src/aria/widgetLibs/BindableWidget.js +++ b/src/aria/widgetLibs/BindableWidget.js @@ -73,37 +73,39 @@ Aria.classDefinition({ * @protected */ _registerBindings : function () { - var bindings = this._cfg.bind, jsonUtils = aria.utils.Json; + var bindings = this._cfg.bind; if (bindings) { for (var property in bindings) { - if (!bindings.hasOwnProperty(property)) { - continue; + if (bindings.hasOwnProperty(property)) { + this._registerSingleProperty(property); } + } + } + }, - var bind = bindings[property]; - if (bind) { - var callback = { - fn : this._notifyDataChange, - scope : this, - args : property - }; + _registerSingleProperty : function (property) { + var bindings = this._cfg.bind, bind = bindings[property], jsonUtils = aria.utils.Json; + if (bind) { + var callback = { + fn : this._notifyDataChange, + scope : this, + args : property + }; - try { - jsonUtils.addListener(bind.inside, bind.to, callback, true); + try { + jsonUtils.addListener(bind.inside, bind.to, callback, true); - this._bindingListeners[property] = { - inside : bind.inside, - to : bind.to, - transform : bind.transform, - cb : callback - }; + this._bindingListeners[property] = { + inside : bind.inside, + to : bind.to, + transform : bind.transform, + cb : callback + }; - var newValue = this._transform(bind.transform, bind.inside[bind.to], "toWidget"); - this.setWidgetProperty(property, newValue); - } catch (ex) { - this.$logError(this.INVALID_BEAN, [property, "bind"]); - } - } + var newValue = this._transform(bind.transform, bind.inside[bind.to], "toWidget"); + this.setWidgetProperty(property, newValue); + } catch (ex) { + this.$logError(this.INVALID_BEAN, [property, "bind"]); } } }, diff --git a/src/aria/widgets/form/list/List.js b/src/aria/widgets/form/list/List.js index a921c8d65..461bd2287 100644 --- a/src/aria/widgets/form/list/List.js +++ b/src/aria/widgets/form/list/List.js @@ -221,6 +221,56 @@ Aria.classDefinition({ // (but this would not be backward-compatible with current list templates) this._subTplCtxt.$refresh(); } + }, + + /** + * Register listeners for the bindings associated to this widget + * @protected + */ + _registerSingleProperty : function (property) { + var bindings = this._cfg.bind, bind = bindings[property]; + + if (bindings && bind && bindings.hasOwnProperty(property) && property === "items") { + var callback = { + fn : this._notifyDataChange, + scope : this, + args : property + }; + try { + aria.utils.Json.addListener(bind.inside, bind.to, callback, true, true); + this._bindingListeners[property] = { + inside : bind.inside, + to : bind.to, + transform : bind.transform, + cb : callback + }; + + var newValue = this._transform(bind.transform, bind.inside[bind.to], "toWidget"); + this._cfg[property] = newValue; + } catch (ex) { + this.$logError(this.INVALID_BEAN, [property, "bind"]); + } + } else { + this.$TemplateBasedWidget._registerSingleProperty.apply(this, arguments); + } + }, + + /** + * Set property for this widget, and reflect change on itself, but not in the associated datamodel + * @param {String} propertyName in the configuration + * @param {Object} newValue to set + */ + setWidgetProperty : function (propertyName, newValue) { + if (!this._cfg) { + return; + } + if (propertyName === "items" && this._cfg.bind.hasOwnProperty(propertyName)) { + var oldValue = this.getProperty(propertyName); + this._cfg[propertyName] = newValue; + this._onBoundPropertyChange(propertyName, newValue, oldValue); + } else { + this.$TemplateBasedWidget.setWidgetProperty.apply(this, arguments); + } } } }); diff --git a/test/aria/widgets/form/FormTestSuite.js b/test/aria/widgets/form/FormTestSuite.js index 386d14e6c..4bf88ff6e 100644 --- a/test/aria/widgets/form/FormTestSuite.js +++ b/test/aria/widgets/form/FormTestSuite.js @@ -25,7 +25,7 @@ Aria.classDefinition({ this.addTests("test.aria.widgets.form.GaugeTest"); this.addTests("test.aria.widgets.form.InputTest"); this.addTests("test.aria.widgets.form.InputValidationHandlerTest"); - this.addTests("test.aria.widgets.form.ListControllerTest"); + this.addTests("test.aria.widgets.form.list.ListTestSuite"); this.addTests("test.aria.widgets.form.numberfield.NumberFieldSuite"); this.addTests("test.aria.widgets.form.PasswordFieldTest"); this.addTests("test.aria.widgets.form.TextareaTest"); diff --git a/test/aria/widgets/form/ListControllerTest.js b/test/aria/widgets/form/list/ListControllerTest.js similarity index 99% rename from test/aria/widgets/form/ListControllerTest.js rename to test/aria/widgets/form/list/ListControllerTest.js index 070e9263a..d98d509c6 100644 --- a/test/aria/widgets/form/ListControllerTest.js +++ b/test/aria/widgets/form/list/ListControllerTest.js @@ -14,7 +14,7 @@ */ Aria.classDefinition({ - $classpath : "test.aria.widgets.form.ListControllerTest", + $classpath : "test.aria.widgets.form.list.ListControllerTest", $extends : "aria.jsunit.TestCase", $dependencies : ["aria.widgets.form.list.ListController", "aria.DomEvent"], $constructor : function () { diff --git a/test/aria/widgets/form/list/ListTestCase.js b/test/aria/widgets/form/list/ListTestCase.js new file mode 100644 index 000000000..c026b1ea6 --- /dev/null +++ b/test/aria/widgets/form/list/ListTestCase.js @@ -0,0 +1,83 @@ +/* + * Copyright 2012 Amadeus s.a.s. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +Aria.classDefinition({ + $classpath : "test.aria.widgets.form.list.ListTestCase", + $extends : "aria.jsunit.TemplateTestCase", + $dependencies : ["aria.utils.Json"], + $constructor : function () { + this.$TemplateTestCase.constructor.call(this); + this.listContainer = null; + this.children = null; + this.data = { + italian : [{ value: "D", label: "Donizetti"}, { value: "B", label: "Bellini" }, { value: "V", label: "Verdi" }] + }; + this.setTestEnv({ + template : "test.aria.widgets.form.list.ListTestCaseTpl", + data : this.data + }); + }, + $destructor : function () { + this.listContainer = null; + this.children = null; + this.$TemplateTestCase.$destructor.call(this); + }, + $prototype : { + runTemplateTest : function () { + this.listContainer = this.getWidgetDomElement("myId", "div"); + this.children = this.getElementsByClassName(this.listContainer, "xListEnabledItem_std"); + + this.assertTrue(this.children.length === 3, "The number of list items is not 3"); + + if (aria.core.Browser.isIE && aria.core.Browser.majorVersion < 9) { + aria.core.Timer.addCallback({ + fn: this.waitForIE, + scope: this, + delay: 500 + }); + } else { + this.addItem(); + this.assertTrue(this.children.length === 4, "The item was not added to the DOM"); + + this.removeItem(); + this.assertTrue(this.children.length === 3, "The item was not removed from the DOM"); + + this.notifyTemplateTestEnd(); + } + }, + + waitForIE : function () { + this.addItem(); + this.listContainer = this.getWidgetDomElement("myId", "div"); + this.children = this.getElementsByClassName(this.listContainer, "xListEnabledItem_std"); + this.assertTrue(this.children.length === 4, "The item was not added to the DOM"); + + this.removeItem(); + this.listContainer = this.getWidgetDomElement("myId", "div"); + this.children = this.getElementsByClassName(this.listContainer, "xListEnabledItem_std"); + this.assertTrue(this.children.length === 3, "The item was not removed from the DOM"); + + this.notifyTemplateTestEnd(); + }, + + addItem : function () { + aria.utils.Json.add(this.data.italian, { value: "p", label: "Puccini"}); + }, + + removeItem : function () { + aria.utils.Json.removeAt(this.data.italian, 3); + } + } +}); diff --git a/test/aria/widgets/form/list/ListTestCaseTpl.tpl b/test/aria/widgets/form/list/ListTestCaseTpl.tpl new file mode 100644 index 000000000..940de94b7 --- /dev/null +++ b/test/aria/widgets/form/list/ListTestCaseTpl.tpl @@ -0,0 +1,40 @@ +/* + * Copyright 2012 Amadeus s.a.s. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{Template { + $classpath : "test.aria.widgets.form.list.ListTestCaseTpl", + $templates : ["aria.widgets.form.list.templates.ListTemplate"] +}} + + {macro main()} + +
+ +

List of Italian composers (bound to data model):

+ {@aria:List { + id: "myId", + minWidth:200, + bind: { + items: { + to: "italian", + inside: data + } + } + }/} + +
+ + {/macro} +{/Template} diff --git a/test/aria/widgets/form/list/ListTestSuite.js b/test/aria/widgets/form/list/ListTestSuite.js new file mode 100644 index 000000000..42dfa6835 --- /dev/null +++ b/test/aria/widgets/form/list/ListTestSuite.js @@ -0,0 +1,24 @@ +/* + * Copyright 2012 Amadeus s.a.s. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +Aria.classDefinition({ + $classpath : "test.aria.widgets.form.list.ListTestSuite", + $extends : "aria.jsunit.TestSuite", + $constructor : function () { + this.$TestSuite.constructor.call(this); + this.addTests("test.aria.widgets.form.list.ListControllerTest"); + this.addTests("test.aria.widgets.form.list.ListTestCase"); + } +});