angularjs - शनश - भारतीय दर्शन का वर्गीकरण




AngularJS-एक निर्देश बनाएं जो एनजी-मॉडल का उपयोग करता है (6)

एक अलग गुंजाइश बनाना अवांछनीय है। मैं स्कोप विशेषता का उपयोग करने से बचूंगा और ऐसा कुछ करूंगा। दायरा: सच आपको एक नया बच्चा गुंजाइश देता है लेकिन अलग नहीं होता है। फिर स्थानीय स्कोप वैरिएबल को उसी ऑब्जेक्ट पर इंगित करने के लिए पार्स का उपयोग करें जिसे उपयोगकर्ता ने ngModel विशेषता प्रदान की है।

app.directive('myDir', ['$parse', function ($parse) {
    return {
        restrict: 'EA',
        scope: true,
        link: function (scope, elem, attrs) {
            if(!attrs.ngModel) {return;}
            var model = $parse(attrs.ngModel);
            scope.model = model(scope);
        }
    };
}]);

मैं एक निर्देश बनाने की कोशिश कर रहा हूं जो उसी एनजी-मॉडल के साथ एक इनपुट फ़ील्ड बनाएगा जो तत्व बनाता है जो निर्देश बनाता है।

यहां तक ​​कि मैं अब तक क्या आया हूं:

एचटीएमएल

<!doctype html>
<html ng-app="plunker" >
<head>
  <meta charset="utf-8">
  <title>AngularJS Plunker</title>
  <link rel="stylesheet" href="style.css">
  <script>document.write("<base href=\"" + document.location + "\" />");</script>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.js"></script>
  <script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
  This scope value <input ng-model="name">
  <my-directive ng-model="name"></my-directive>
</body>
</html>

जावास्क्रिप्ट

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {
  $scope.name = "Felipe";
});

app.directive('myDirective', function($compile) {
  return {
    restrict: 'E',
    scope: {
      ngModel: '='
    },
    template: '<div class="some"><label for="{{id}}">{{label}}</label>' +
      '<input id="{{id}}" ng-model="value"></div>',
    replace: true,
    require: 'ngModel',
    link: function($scope, elem, attr, ctrl) {
      $scope.label = attr.ngModel;
      $scope.id = attr.ngModel;
      console.debug(attr.ngModel);
      console.debug($scope.$parent.$eval(attr.ngModel));
      var textField = $('input', elem).
        attr('ng-model', attr.ngModel).
        val($scope.$parent.$eval(attr.ngModel));

      $compile(textField)($scope.$parent);
    }
  };
});

हालांकि, मुझे विश्वास नहीं है कि यह परिदृश्य को संभालने का यह सही तरीका है, और एक बग है कि मेरा नियंत्रण एनजी-मॉडल लक्ष्य फ़ील्ड के मूल्य के साथ प्रारंभ नहीं हो रहा है।

यहां उपरोक्त कोड का प्लंकर है: http://plnkr.co/edit/IvrDbJ

इसे संभालने का सही तरीका क्या है?

संपादित करें : टेम्पलेट से ng-model="value" को हटाने के बाद, यह ठीक काम कर रहा है। हालांकि, मैं इस प्रश्न को खुला रखूंगा क्योंकि मैं दोबारा जांचना चाहता हूं कि यह करने का यह सही तरीका है।


कोणीय 1.5 के बाद से घटक का उपयोग करना संभव है। घटक रास्ते-रास्ते जाते हैं और इस समस्या को हल करते हैं।

<myComponent data-ng-model="$ctrl.result"></myComponent>

app.component("myComponent", {
    templateUrl: "yourTemplate.html",
    controller: YourController,
    bindings: {
        ngModel: "="
    }
});

आपके कंट्रोलर के अंदर आपको बस इतना करना है:

this.ngModel = "x"; //$scope.$apply("$ctrl.ngModel"); if needed

मैं एक विशेषता के माध्यम से ngmodel सेट नहीं होगा, आप इसे टेम्पलेट में सही निर्दिष्ट कर सकते हैं:

template: '<div class="some"><label>{{label}}</label><input data-ng-model="ngModel"></div>',

प्लंकर : http://plnkr.co/edit/9vtmnw?p=preview


मैंने सभी उत्तरों का कॉम्बो लिया, और अब एनजी-मॉडल विशेषता के साथ ऐसा करने के दो तरीके हैं:

  • एक नए दायरे के साथ जो ngModel प्रतिलिपि बनाता है
  • उसी दायरे के साथ जो लिंक पर संकलन करता है

var app = angular.module('model', []);

app.controller('MainCtrl', function($scope) {
  $scope.name = "Felipe";
  $scope.label = "The Label";
});

app.directive('myDirectiveWithScope', function() {
  return {
    restrict: 'E',
    scope: {
      ngModel: '=',
    },
    // Notice how label isn't copied
    template: '<div class="some"><label>{{label}}: <input ng-model="ngModel"></label></div>',
    replace: true
  };
});
app.directive('myDirectiveWithChildScope', function($compile) {
  return {
    restrict: 'E',
    scope: true,
    // Notice how label is visible in the scope
    template: '<div class="some"><label>{{label}}: <input></label></div>',
    replace: true,
    link: function ($scope, element) {
      // element will be the div which gets the ng-model on the original directive
      var model = element.attr('ng-model');
      $('input',element).attr('ng-model', model);
      return $compile(element)($scope);
    }
  };
});
app.directive('myDirectiveWithoutScope', function($compile) {
  return {
    restrict: 'E',
    template: '<div class="some"><label>{{$parent.label}}: <input></label></div>',
    replace: true,
    link: function ($scope, element) {
      // element will be the div which gets the ng-model on the original directive
      var model = element.attr('ng-model');
      return $compile($('input',element).attr('ng-model', model))($scope);
    }
  };
});
app.directive('myReplacedDirectiveIsolate', function($compile) {
  return {
    restrict: 'E',
    scope: {},
    template: '<input class="some">',
    replace: true
  };
});
app.directive('myReplacedDirectiveChild', function($compile) {
  return {
    restrict: 'E',
    scope: true,
    template: '<input class="some">',
    replace: true
  };
});
app.directive('myReplacedDirective', function($compile) {
  return {
    restrict: 'E',
    template: '<input class="some">',
    replace: true
  };
});
.some {
  border: 1px solid #cacaca;
  padding: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.min.js"></script>
<div ng-app="model" ng-controller="MainCtrl">
  This scope value <input ng-model="name">, label: "{{label}}"
  <ul>
    <li>With new isolate scope (label from parent):
      <my-directive-with-scope ng-model="name"></my-directive-with-scope>
    </li>
    <li>With new child scope:
      <my-directive-with-child-scope ng-model="name"></my-directive-with-child-scope>
    </li>
    <li>Same scope:
      <my-directive-without-scope ng-model="name"></my-directive-without-scope>
    </li>
    <li>Replaced element, isolate scope:
      <my-replaced-directive-isolate ng-model="name"></my-replaced-directive-isolate>
    </li>
    <li>Replaced element, child scope:
      <my-replaced-directive-child ng-model="name"></my-replaced-directive-child>
    </li>
    <li>Replaced element, same scope:
      <my-replaced-directive ng-model="name"></my-replaced-directive>
    </li>
  </ul>
  <p>Try typing in the child scope ones, they copy the value into the child scope which breaks the link with the parent scope.
  <p>Also notice how removing jQuery makes it so only the new-isolate-scope version works.
  <p>Finally, note that the replace+isolate scope only works in AngularJS >=1.2.0
</div>

मुझे यकीन नहीं है कि मुझे लिंक समय पर संकलन पसंद है। हालांकि, अगर आप तत्व को दूसरे के साथ बदल रहे हैं तो आपको ऐसा करने की आवश्यकता नहीं है।

सब कुछ मैं सबसे पहले पसंद करता हूं। बस {ngModel:"="} को दायरा सेट करें और ng-model="ngModel" सेट करें जहां आप इसे अपने टेम्पलेट में चाहते हैं।

अपडेट करें : मैंने कोड स्निपेट को रेखांकित किया और इसे कोणीय v1.2 के लिए अपडेट किया। अलग-अलग स्कोप अभी भी सर्वोत्तम है, खासकर जब jQuery का उपयोग नहीं करते हैं। तो यह नीचे उबलता है:

  • क्या आप एक तत्व को बदल रहे हैं: बस इसे प्रतिस्थापित करें, अकेले दायरे को छोड़ दें, लेकिन ध्यान दें कि v2.0 के लिए प्रतिस्थापित किया गया है:

    app.directive('myReplacedDirective', function($compile) {
      return {
        restrict: 'E',
        template: '<input class="some">',
        replace: true
      };
    });
    
  • अन्यथा इसका उपयोग करें:

    app.directive('myDirectiveWithScope', function() {
      return {
        restrict: 'E',
        scope: {
          ngModel: '=',
        },
        template: '<div class="some"><input ng-model="ngModel"></div>'
      };
    });
    

यह थोड़ा देर से जवाब है, लेकिन मुझे NgModelController बारे में यह भयानक post मिला, जो मुझे लगता है कि आप वास्तव में क्या खोज रहे हैं।

टीएल; डीआर - आप require: 'ngModel' उपयोग कर सकते हैं require: 'ngModel' और फिर अपने लिंकिंग फ़ंक्शन में NgModelController जोड़ें:

link: function(scope, iElement, iAttrs, ngModelCtrl) {
  //TODO
}

इस तरह, कोई हैक की आवश्यकता नहीं है - आप कोणीय के अंतर्निर्मित ng-model का उपयोग कर रहे हैं


यह वास्तव में बहुत अच्छा तर्क है लेकिन आप चीजों को थोड़ा सा सरल बना सकते हैं।

आदेश

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {
  $scope.model = { name: 'World' };
  $scope.name = "Felipe";
});

app.directive('myDirective', function($compile) {
  return {
    restrict: 'AE', //attribute or element
    scope: {
      myDirectiveVar: '=',
     //bindAttr: '='
    },
    template: '<div class="some">' +
      '<input ng-model="myDirectiveVar"></div>',
    replace: true,
    //require: 'ngModel',
    link: function($scope, elem, attr, ctrl) {
      console.debug($scope);
      //var textField = $('input', elem).attr('ng-model', 'myDirectiveVar');
      // $compile(textField)($scope.$parent);
    }
  };
});

निर्देश के साथ एचटीएमएल

<body ng-controller="MainCtrl">
  This scope value <input ng-model="name">
  <my-directive my-directive-var="name"></my-directive>
</body>

सीएसएस

.some {
  border: 1px solid #cacaca;
  padding: 10px;
}

आप इसे इस Plunker साथ कार्रवाई में देख सकते हैं।

मैं जो देखता हूं वह यहां है:

  • मैं समझता हूं कि आप 'एनजी-मॉडल' का उपयोग क्यों करना चाहते हैं लेकिन आपके मामले में यह आवश्यक नहीं है। एनजी-मॉडल मौजूदा एचटीएमएल तत्वों को दायरे में एक मूल्य के साथ जोड़ना है। चूंकि आप स्वयं निर्देश बना रहे हैं, इसलिए आप एक 'नया' HTML तत्व बना रहे हैं, इसलिए आपको एनजी-मॉडल की आवश्यकता नहीं है।

संपादित करें जैसा कि मार्क ने अपनी टिप्पणी में उल्लेख किया है, इस बात का कोई कारण नहीं है कि आप सम्मेलन के साथ रखने के लिए एनजी मॉडल का उपयोग नहीं कर सकते हैं

  • स्पष्ट रूप से आपके निर्देश (एक 'पृथक' गुंजाइश) में एक दायरा बनाकर, निर्देश का दायरा माता-पिता के दायरे पर 'नाम' चर का उपयोग नहीं कर सकता है (यही कारण है कि, मुझे लगता है कि आप एनजी-मॉडल का उपयोग करना चाहते थे)।
  • मैंने आपके निर्देश से ngModel को हटा दिया और इसे एक कस्टम नाम से बदल दिया जिसे आप जो भी बदल सकते हैं।
  • यह चीज जो इसे अभी भी काम करती है वह यह है कि '=' दायरे में साइन इन करें। 'स्कोप' हेडर के नीचे दस्तावेज़ docs को चेकआउट करें।

आम तौर पर, आपके निर्देशों को अलग-अलग दायरे का उपयोग करना चाहिए (जिसे आपने सही तरीके से किया है) और '=' प्रकार के दायरे का उपयोग करना चाहिए यदि आप अपने निर्देश में मूल्य हमेशा माता-पिता के दायरे में किसी मान को मैप करना चाहते हैं।





directive