Skip to content
This repository was archived by the owner on Mar 17, 2025. It is now read-only.

Can't set $priority in $bindTo/$scope variable in 0.8 #333

Closed
katowulf opened this issue Jul 16, 2014 · 9 comments
Closed

Can't set $priority in $bindTo/$scope variable in 0.8 #333

katowulf opened this issue Jul 16, 2014 · 9 comments

Comments

@katowulf
Copy link
Contributor

It looks like Angular's $watch methods do not trigger for variables prefixed with $ using Angular 1.2.18. So setting $priority does not trigger the 3-way binding as intended. Same is true for $value.

See disabled xit tests for these two conditions in the spec.

katowulf added a commit that referenced this issue Jul 16, 2014
…ot working ideally with $bindTo, see #333

E2e tests are busted for now until Jacob gets his groove on.
@katowulf
Copy link
Contributor Author

This is also an issue with Angular v1.3.0-beta.15--tested this a.m. We'll need to decide on a workaround here.

@joshbowdoin
Copy link
Contributor

With the changes to Angular (not stripping single '$' prefixed properties from toJson, but only stripping '$$' prefixed properties), this seems more like a bug in Angular. A remnant of the way it used to work?

@katowulf
Copy link
Contributor Author

Internally, $watch uses angular.equals, which checks for $ prefixes : (

/**
 * @ngdoc function
 * @name angular.equals
 * @module ng
 * @kind function
 *
 * @description
 * Determines if two objects or two values are equivalent. Supports value types, regular
 * expressions, arrays and objects.
 *
 * Two objects or values are considered equivalent if at least one of the following is true:
 *
 * * Both objects or values pass `===` comparison.
 * * Both objects or values are of the same type and all of their properties are equal by
 *   comparing them with `angular.equals`.
 * * Both values are NaN. (In JavaScript, NaN == NaN => false. But we consider two NaN as equal)
 * * Both values represent the same regular expression (In JavaScript,
 *   /abc/ == /abc/ => false. But we consider two regular expressions as equal when their textual
 *   representation matches).
 *
 * During a property comparison, properties of `function` type and properties with names
 * that begin with `$` are ignored.
 *
 * Scope and DOMWindow objects are being compared only by identify (`===`).
 *
 * @param {*} o1 Object or value to compare.
 * @param {*} o2 Object or value to compare.
 * @returns {boolean} True if arguments are equal.
 */
function equals(o1, o2) {
  if (o1 === o2) return true;
  if (o1 === null || o2 === null) return false;
  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN
  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;
  if (t1 == t2) {
    if (t1 == 'object') {
      if (isArray(o1)) {
        if (!isArray(o2)) return false;
        if ((length = o1.length) == o2.length) {
          for(key=0; key<length; key++) {
            if (!equals(o1[key], o2[key])) return false;
          }
          return true;
        }
      } else if (isDate(o1)) {
        return isDate(o2) && o1.getTime() == o2.getTime();
      } else if (isRegExp(o1) && isRegExp(o2)) {
        return o1.toString() == o2.toString();
      } else {
        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) || isArray(o2)) return false;
        keySet = {};
        for(key in o1) {
          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;
          if (!equals(o1[key], o2[key])) return false;
          keySet[key] = true;
        }
        for(key in o2) {
          if (!keySet.hasOwnProperty(key) &&
              key.charAt(0) !== '$' &&
              o2[key] !== undefined &&
              !isFunction(o2[key])) return false;
        }
        return true;
      }
    }
  }
  return false;
}

@joshbowdoin
Copy link
Contributor

With them changing toJSON to only care about $$, it seems to me like that line should be changed from
if (key.charAt(0) === '$' || isFunction(o1[key])) continue;
to
if ((key.charAt(0) === '$' && key.charAt(1) === '$') || isFunction(o1[key])) continue;
to be consistent with their changes in the rest of the framework. (the line below that would also have to be changed)

All internal properties that shouldn't be watched have $$ (as far as I know).

Their whole reason for the change was that some frameworks use single $ properties (and couldn't easily change that). So, this would also need to be updated, in my opinion.

@joshbowdoin
Copy link
Contributor

Slight update... there is $parent, $root, etc on the scope, so maybe that is why they aren't wanting to watch those properties? But if that is the case, then their change will just introduce bugs for those frameworks that now expect to be able to use single $.

See these:
angular/angular.js#1463
angular/angular.js#6253

@joshbowdoin
Copy link
Contributor

(I really don't want to have to use '.priority' - can you tell? :) )

@katowulf
Copy link
Contributor Author

Me either. I can't find any way to fix this from our end though. We're going to brainstorm some ideas this afternoon. I'll report our findings back here.

@jwngr jwngr added bug labels Jul 17, 2014
@katowulf
Copy link
Contributor Author

For now, the solution is simply going to be that you can't set $value or $priority from within $bindTo. If you want to set those values, you'll need to manually trigger $save in order for the sync to take place (or also edit a field that is checked by Angular).

@katowulf
Copy link
Contributor Author

katowulf commented Aug 1, 2014

See also angular/angular.js#8325

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants