Skip to content
This repository was archived by the owner on Feb 22, 2018. It is now read-only.

Cannot use map keys in ng-model that are not strings #608

Closed
davidpolberger opened this issue Feb 25, 2014 · 1 comment
Closed

Cannot use map keys in ng-model that are not strings #608

davidpolberger opened this issue Feb 25, 2014 · 1 comment

Comments

@davidpolberger
Copy link

Referencing a map value in ng-model where the keys of the map are not strings results in an exception being thrown. Consider this markup:

<form ng-repeat="field in cmp.fields">
  <div contenteditable ng-model="cmp.map[field]"></div>
</form>

(Where the type of cmp.fields is Map<Field, String>.)

Error, including stack trace:

type 'String' is not a subtype of type 'Field' of 'key'.

STACKTRACE:
#0      _HashMap.[]= (dart:collection-patch/collection_patch.dart:95)
#1      setKeyed (package:angular/core/parser/utils.dart:93:11)
#2      AccessKeyed.assign (package:angular/core/parser/eval_access.dart:47:35)
#3      DynamicExpression.assign (package:angular/core/parser/dynamic_parser.dart:59:32)
#4      DynamicExpression.assign (package:angular/core/parser/dynamic_parser.dart:60:7)
#5      assign (package:angular/core/parser/syntax.dart:78:47)
#6      NgModel.modelValue= (package:angular/directive/ng_model.dart:80:34)
#7      NgModel.viewValue= (package:angular/directive/ng_model.dart:77:27)
#8      InputTextLikeDirective.processValue.<anonymous closure> (package:angular/directive/ng_model.dart:204:34)
#9      relaxFnArgs.<anonymous closure> (package:angular/utils.dart:72:40)
#10     Scope.$eval (package:angular/core/scope.dart:701:43)
#11     Scope.$apply.<anonymous closure> (package:angular/core/scope.dart:765:21)
#12     _rootRun (dart:async/zone.dart:683)
#13     _ZoneDelegate.run (dart:async/zone.dart:417)
#14     _onRun.<anonymous closure> (package:angular/core/zone.dart:61:56)
#15     NgZone._onRunBase (package:angular/core/zone.dart:49:16)
#16     _onRun (package:angular/core/zone.dart:61:15)
#17     _ZoneDelegate.run (dart:async/zone.dart:417)
#18     _CustomizedZone.run (dart:async/zone.dart:627)
#19     NgZone.run (package:angular/core/zone.dart:143:27)
#20     Scope.$apply (package:angular/core/scope.dart:761:21)
#21     InputTextLikeDirective.processValue (package:angular/directive/ng_model.dart:204:19)
#22     InputTextLikeDirective.InputTextLikeDirective.<anonymous closure> (package:angular/directive/ng_model.dart:196:23)
#23     _rootRunUnary (dart:async/zone.dart:700)
#24     _ZoneDelegate.runUnary (dart:async/zone.dart:426)
#25     _onRunUnary.<anonymous closure> (package:angular/core/zone.dart:65:61)
#26     NgZone._onRunBase (package:angular/core/zone.dart:49:16)
#27     _onRunUnary (package:angular/core/zone.dart:65:15)
#28     _ZoneDelegate.runUnary (dart:async/zone.dart:426)
#29     _CustomizedZone.runUnary (dart:async/zone.dart:631)
#30     _BaseZone.runUnaryGuarded (dart:async/zone.dart:546)
#31     _BaseZone.bindUnaryCallback.<anonymous closure> (dart:async/zone.dart:572)

The problem is in package:angular/core/parser/utils.dart, specifically in the getKeyed() and setKeyed() methods, which treat instances of the List and Map classes specially. For maps, the existing code assumes that keys are always strings:

/// Set a keyed element in the given [object].
setKeyed(object, key, value) {
  if (object is List) {
    int index = key.toInt();
    if (object.length <= index) object.length = index + 1;
    object[index] = value;
  } else if (object is Map) {
    object["$key"] = value; // toString dangerous?
  } else {
    object[key] = value;
  }
  return value;
}

The fix is simple: simply remove the Map-specific code:

/// Set a keyed element in the given [object].
setKeyed(object, key, value) {
  if (object is List) {
    int index = key.toInt();
    if (object.length <= index) object.length = index + 1;
    object[index] = value;
  } else {
    object[key] = value;
  }
  return value;
}

(This fix needs to be applied to getKeyed() as well.)

This fix works well locally -- should I submit a pull request?

davidpolberger added a commit to davidpolberger/angular.dart that referenced this issue Feb 26, 2014
The parser utility functions getKeyed() and setKeyed() treat instances
of the List and Map classes specially. For maps, the existing code
assumes that keys are always strings. If that is not the case, an
exception is likely thrown by the Map implementation. As map keys are
not necessarily strings, and there is code that handles generic
instances just fine, this commit simply removes the code that treats
maps specially.

Closes dart-archive#608
@mhevery
Copy link
Contributor

mhevery commented Apr 9, 2014

Fixed by: 03f0a4c

@mhevery mhevery closed this as completed Apr 9, 2014
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Development

Successfully merging a pull request may close this issue.

2 participants