Skip to content

Commit 397319e

Browse files
committed
Data-value should only respond to change events targeted at self
Avoids values being changed when using data-value on parent elements.
1 parent 9fbdf90 commit 397319e

File tree

3 files changed

+95
-30
lines changed

3 files changed

+95
-30
lines changed

Source/Core/DataControllerDefault.cpp

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -33,29 +33,30 @@ bool DataControllerValue::Initialize(DataModel& model, Element* element, const S
3333

3434
void DataControllerValue::ProcessEvent(Event& event)
3535
{
36-
if (const Element* element = GetElement())
37-
{
38-
Variant value_to_set;
39-
const auto& parameters = event.GetParameters();
40-
const auto override_value_it = parameters.find("data-binding-override-value");
41-
const auto value_it = parameters.find("value");
42-
if (override_value_it != parameters.cend())
43-
value_to_set = override_value_it->second;
44-
else if (value_it != parameters.cend())
45-
value_to_set = value_it->second;
46-
else
47-
Log::Message(Log::LT_WARNING,
48-
"A 'change' event was received, but it did not contain the attribute 'value' when processing a data binding in %s",
49-
element->GetAddress().c_str());
50-
51-
DataModel* model = element->GetDataModel();
52-
if (value_to_set.GetType() == Variant::NONE || !model)
53-
return;
54-
55-
if (DataVariable variable = model->GetVariable(address))
56-
if (variable.Set(value_to_set))
57-
model->DirtyVariable(address.front().name);
58-
}
36+
Element* element = GetElement();
37+
if (!element || event.GetTargetElement() != element)
38+
return;
39+
40+
Variant value_to_set;
41+
const auto& parameters = event.GetParameters();
42+
const auto override_value_it = parameters.find("data-binding-override-value");
43+
const auto value_it = parameters.find("value");
44+
if (override_value_it != parameters.cend())
45+
value_to_set = override_value_it->second;
46+
else if (value_it != parameters.cend())
47+
value_to_set = value_it->second;
48+
else
49+
Log::Message(Log::LT_WARNING,
50+
"A 'change' event was received, but it did not contain the attribute 'value' when processing a data binding in %s",
51+
element->GetAddress().c_str());
52+
53+
DataModel* model = element->GetDataModel();
54+
if (value_to_set.GetType() == Variant::NONE || !model)
55+
return;
56+
57+
if (DataVariable variable = model->GetVariable(address))
58+
if (variable.Set(value_to_set))
59+
model->DirtyVariable(address.front().name);
5960
}
6061

6162
void DataControllerValue::Release()
@@ -102,12 +103,13 @@ void DataControllerEvent::ProcessEvent(Event& event)
102103
if (!expression)
103104
return;
104105

105-
if (Element* element = GetElement())
106-
{
107-
DataExpressionInterface expr_interface(element->GetDataModel(), element, &event);
108-
Variant unused_value_out;
109-
expression->Run(expr_interface, unused_value_out);
110-
}
106+
Element* element = GetElement();
107+
if (!element)
108+
return;
109+
110+
DataExpressionInterface expr_interface(element->GetDataModel(), element, &event);
111+
Variant unused_value_out;
112+
expression->Run(expr_interface, unused_value_out);
111113
}
112114

113115
void DataControllerEvent::Release()

Source/Core/DataViewDefault.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ class DataViewCommon : public DataView {
2323
const String& GetModifier() const;
2424
DataExpression& GetExpression();
2525

26-
// Delete this
2726
void Release() override;
2827

2928
private:

Tests/Source/UnitTests/DataBinding.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -763,3 +763,67 @@ TEST_CASE("data_binding.data_model_on_body")
763763
document->Close();
764764
TestsShell::ShutdownShell();
765765
}
766+
767+
TEST_CASE("data_binding.data-value")
768+
{
769+
Context* context = TestsShell::GetContext();
770+
REQUIRE(context);
771+
772+
static const String document_rml = R"(
773+
<rml>
774+
<head>
775+
<title>Test</title>
776+
<link type="text/template" href="/assets/window.rml"/>
777+
</head>
778+
<body template="window" data-model="text">
779+
<div id="div" data-value="parent">
780+
<p id="p">{{ name }}</p>
781+
<input id="input" type="text" data-value="name"/>
782+
</div>
783+
</body>
784+
</rml>
785+
)";
786+
787+
Rml::DataModelConstructor constructor = context->CreateDataModel("text");
788+
REQUIRE(constructor);
789+
790+
Rml::String name = "name";
791+
Rml::String parent = "parent";
792+
793+
constructor.Bind("name", &name);
794+
constructor.Bind("parent", &parent);
795+
796+
DataModelHandle handle = constructor.GetModelHandle();
797+
798+
ElementDocument* document = context->LoadDocumentFromMemory(document_rml);
799+
REQUIRE(document);
800+
document->Show();
801+
802+
TestsShell::RenderLoop();
803+
804+
Element* div = document->GetElementById("div");
805+
Element* p = document->GetElementById("p");
806+
Element* input = document->GetElementById("input");
807+
808+
REQUIRE(p->GetInnerRML() == "name");
809+
REQUIRE(input->GetAttribute<String>("value", "") == "name");
810+
REQUIRE(div->GetAttribute<String>("value", "") == "parent");
811+
812+
name = "ant";
813+
handle.DirtyVariable("name");
814+
TestsShell::RenderLoop();
815+
REQUIRE(p->GetInnerRML() == "ant");
816+
REQUIRE(input->GetAttribute<String>("value", "") == "ant");
817+
REQUIRE(div->GetAttribute<String>("value", "") == "parent");
818+
819+
input->Focus();
820+
context->ProcessTextInput("cheerful ");
821+
TestsShell::RenderLoop();
822+
REQUIRE(name == "cheerful ant");
823+
REQUIRE(p->GetInnerRML() == "cheerful ant");
824+
REQUIRE(input->GetAttribute<String>("value", "") == "cheerful ant");
825+
REQUIRE(div->GetAttribute<String>("value", "") == "parent");
826+
827+
document->Close();
828+
TestsShell::ShutdownShell();
829+
}

0 commit comments

Comments
 (0)