@@ -83,18 +83,72 @@ class ElementBinder {
83
83
bool get hasDirectivesOrEvents =>
84
84
_usableDirectiveRefs.isNotEmpty || onEvents.isNotEmpty;
85
85
86
- _createAttrMappings (controller, scope, DirectiveRef ref, nodeAttrs, formatters, tasks) {
87
- ref.mappings.forEach ((MappingParts p) {
86
+ _bindTwoWay (tasks, expression, scope, dstPathFn, controller, formatters, dstExpression) {
87
+ var taskId = tasks.registerTask ();
88
+ Expression expressionFn = _parser (expression);
89
+
90
+ var viewOutbound = false ;
91
+ var viewInbound = false ;
92
+ scope.watch (expression, (inboundValue, _) {
93
+ if (! viewInbound) {
94
+ viewOutbound = true ;
95
+ scope.rootScope.runAsync (() => viewOutbound = false );
96
+ var value = dstPathFn.assign (controller, inboundValue);
97
+ tasks.completeTask (taskId);
98
+ return value;
99
+ }
100
+ }, formatters: formatters);
101
+ if (expressionFn.isAssignable) {
102
+ scope.watch (dstExpression, (outboundValue, _) {
103
+ if (! viewOutbound) {
104
+ viewInbound = true ;
105
+ scope.rootScope.runAsync (() => viewInbound = false );
106
+ expressionFn.assign (scope.context, outboundValue);
107
+ tasks.completeTask (taskId);
108
+ }
109
+ }, context: controller, formatters: formatters);
110
+ }
111
+ }
112
+
113
+ _bindOneWay (tasks, expression, scope, dstPathFn, controller, formatters) {
114
+ var taskId = tasks.registerTask ();
115
+
116
+ Expression attrExprFn = _parser (expression);
117
+ scope.watch (expression, (v, _) {
118
+ dstPathFn.assign (controller, v);
119
+ tasks.completeTask (taskId);
120
+ }, formatters: formatters);
121
+ }
122
+
123
+ _bindCallback (dstPathFn, controller, expression, scope) {
124
+ dstPathFn.assign (controller, _parser (expression).bind (scope.context, ScopeLocals .wrapper));
125
+ }
126
+
127
+ _createAttrMappings (controller, scope, List <MappingParts > mappings, nodeAttrs, formatters, tasks) {
128
+ mappings.forEach ((MappingParts p) {
88
129
var attrName = p.attrName;
89
130
var dstExpression = p.dstExpression;
90
- if (nodeAttrs == null ) nodeAttrs = new _AnchorAttrs (ref);
91
131
92
132
Expression dstPathFn = _parser (dstExpression);
93
133
if (! dstPathFn.isAssignable) {
94
134
throw "Expression '$dstExpression ' is not assignable in mapping '${p .originalValue }' "
95
135
"for attribute '$attrName '." ;
96
136
}
97
137
138
+ // Check if there is a bind attribute for this mapping.
139
+ var bindAttr = bindAttrs["bind-${p .attrName }" ];
140
+ if (bindAttr != null ) {
141
+ if (p.mode == '<=>' ) {
142
+ _bindTwoWay (tasks, bindAttr, scope, dstPathFn,
143
+ controller, formatters, dstExpression);
144
+ } else if (p.mode == '&' ) {
145
+ _bindCallback (dstPathFn, controller, bindAttr, scope);
146
+ } else {
147
+ _bindOneWay (tasks, bindAttr, scope, dstPathFn, controller, formatters);
148
+ }
149
+ return ;
150
+ }
151
+
98
152
switch (p.mode) {
99
153
case '@' : // string
100
154
var taskId = tasks.registerTask ();
@@ -107,41 +161,14 @@ class ElementBinder {
107
161
case '<=>' : // two-way
108
162
if (nodeAttrs[attrName] == null ) return ;
109
163
110
- var taskId = tasks.registerTask ();
111
- String expression = nodeAttrs[attrName];
112
- Expression expressionFn = _parser (expression);
113
- var viewOutbound = false ;
114
- var viewInbound = false ;
115
- scope.watch (expression, (inboundValue, _) {
116
- if (! viewInbound) {
117
- viewOutbound = true ;
118
- scope.rootScope.runAsync (() => viewOutbound = false );
119
- var value = dstPathFn.assign (controller, inboundValue);
120
- tasks.completeTask (taskId);
121
- return value;
122
- }
123
- }, formatters: formatters);
124
- if (expressionFn.isAssignable) {
125
- scope.watch (dstExpression, (outboundValue, _) {
126
- if (! viewOutbound) {
127
- viewInbound = true ;
128
- scope.rootScope.runAsync (() => viewInbound = false );
129
- expressionFn.assign (scope.context, outboundValue);
130
- tasks.completeTask (taskId);
131
- }
132
- }, context: controller, formatters: formatters);
133
- }
164
+ _bindTwoWay (tasks, nodeAttrs[attrName], scope, dstPathFn,
165
+ controller, formatters, dstExpression);
134
166
break ;
135
167
136
168
case '=>' : // one-way
137
169
if (nodeAttrs[attrName] == null ) return ;
138
- var taskId = tasks.registerTask ();
139
-
140
- Expression attrExprFn = _parser (nodeAttrs[attrName]);
141
- scope.watch (nodeAttrs[attrName], (v, _) {
142
- dstPathFn.assign (controller, v);
143
- tasks.completeTask (taskId);
144
- }, formatters: formatters);
170
+ _bindOneWay (tasks, nodeAttrs[attrName], scope,
171
+ dstPathFn, controller, formatters);
145
172
break ;
146
173
147
174
case '=>!' : // one-way, one-time
@@ -157,8 +184,7 @@ class ElementBinder {
157
184
break ;
158
185
159
186
case '&' : // callback
160
- dstPathFn.assign (controller,
161
- _parser (nodeAttrs[attrName]).bind (scope.context, ScopeLocals .wrapper));
187
+ _bindCallback (dstPathFn, controller, nodeAttrs[attrName], scope);
162
188
break ;
163
189
}
164
190
});
@@ -182,7 +208,10 @@ class ElementBinder {
182
208
if (scope.isAttached) controller.attach ();
183
209
} : null );
184
210
185
- _createAttrMappings (controller, scope, ref, nodeAttrs, formatters, tasks);
211
+ if (ref.mappings.isNotEmpty) {
212
+ if (nodeAttrs == null ) nodeAttrs = new _AnchorAttrs (ref);
213
+ _createAttrMappings (controller, scope, ref.mappings, nodeAttrs, formatters, tasks);
214
+ }
186
215
187
216
if (controller is AttachAware ) {
188
217
var taskId = tasks.registerTask ();
0 commit comments