The “with” binding of KnockoutJS in AngularJS?

后端 未结 3 1125
小鲜肉
小鲜肉 2021-01-01 16:22

I have just switched from KnockoutJS to AngularJS and I am not able to find the KnockoutJS\'s \"with\" data-bind in AngularJS.

Here is the piece of code in KnockoutJ

相关标签:
3条回答
  • 2021-01-01 16:38

    Nothing like with that I know of.. this is the best I could do:

    <h1>{{city}}</h1>
    <p ng-repeat="c in [coords.or.possibly.deeper.in.tree]">
        Latitude: {{c.latitude}},
        Longitude: {{c.longitude}}
    </p>
    
    0 讨论(0)
  • 2021-01-01 16:51

    Create a custom directive that loops through the source object and creates corresponding properties on the directive's scope that are getter/setter references to the source object.

    Check out this plunker.

    directive module:

    angular.module('koWith', [])
      .directive('koWith', function () {
        return {
          controller: function ($scope, $attrs) {
            var withObj = $scope.$parent[$attrs.ngWith];
    
            function getter(prop) {
              return this[prop];
            }
            function setter(val, prop) {
              this[prop] = val;
            }
    
            for (var prop in withObj) {
              if (withObj.hasOwnProperty(prop)) {
                Object.defineProperty($scope, prop, {
                  enumerable: true,
                  configurable: true,
                  get: getter.bind(withObj, prop),
                  set: setter.bind(withObj, prop)
                });
              }
            }
          },
          restrict: 'A',
          scope: true
        };
      });
    

    app module:

    angular.module('myApp', [])
      .controller('myController', function ($scope) {
        $scope.customer = {
          name: "Timmeh",
          address: {
            address1: "12 S Street",
            address2: "",
            city: "South Park",
            state: "CO",
            zipCode: "80440"
          }
        };
      });
    

    html:

    <div ko-with="customer">
      <h2>{{name}}</h2>
      <div ko-with="address">
        {{address1}}<br>
        {{address2}}<br>
        {{city}}, {{state}} {{zipCode}}
      </div>
    </div>
    

    Explanation

    In KnockoutJS, bindings keep the bindingContext and data separated so creating the with binding is trivial since it only needs to create a new child bindingContext from the current one and use the with object as its data value.

    In AngularJS, a directive's scope is basically the bindingContext and data object rolled into one. When a new scope is created, in order to get the with-like behavior, the properties of the with object have to be referenced onto the newly created scope object.

    0 讨论(0)
  • 2021-01-01 16:52

    Here is solution based on @nwayve, but it supports expressions in koWith and also it watches for updating property/expression specified in koWith:

    .directive('koWith', function () {
    return {
        restrict: 'A',
        scope: true,
        controller: function ($scope, $attrs, $parse) {
            var ScopePropertyDesc = function (prop) {
                var self = this;
                self.propName = prop;
                self.parsed = $parse(prop);
                self.enumerable = true;
                self.configurable = true;
                //self.writable = true;
                self.get = function () {
                    var withObj = $scope.$parent[$attrs.koWith];
                    var res = self.parsed($scope.$parent, withObj);
                    return res;
                };
                self.set = function (newValue) {
                    var withObj = $scope.$parent[$attrs.koWith];
                    self.parsed.assign(withObj, newValue);
                };
            };
    
            $scope.$parent.$watch($attrs.koWith, function (oldVal, newVal) {
                var withObj = $scope.$parent[$attrs.koWith];
    
                (function copyPropertiesToScope(withObj) {
                    for (var prop in withObj) {
                        if (withObj.hasOwnProperty(prop)) {
                            Object.defineProperty($scope, prop, new ScopePropertyDesc(prop));
                        }
                    };
                })(withObj);
            });
        }
    };
    });

    0 讨论(0)
提交回复
热议问题