AngularJS: एनजी-रिपीट लिस्ट तब अपडेट नहीं होती है जब किसी मॉडल एलीमेंट को मॉडल ऐरे से स्पिक किया जाता है


100

मेरे पास दो नियंत्रक हैं और एक app.factory फ़ंक्शन के साथ उनके बीच डेटा साझा करते हैं।

किसी लिंक पर क्लिक करने पर पहला कंट्रोलर मॉडल ऐरे (प्लग-इनप्लेस्ड) में एक विजेट जोड़ता है। विजेट को सरणी में धकेल दिया जाता है और यह परिवर्तन दृश्य में परिलक्षित होता है (जो सरणी सामग्री दिखाने के लिए एनजी-रिपीट का उपयोग करता है):

<div ng-repeat="pluginD in pluginsDisplayed">
    <div k2plugin pluginname="{{pluginD.name}}" pluginid="{{pluginD.id}}"></div>
</div>

विजेट तीन निर्देशों में बनाया गया है, k2plugin, निकालें और आकार बदलें। हटाने का निर्देश k2plugin निर्देश के टेम्पलेट में एक स्पैन जोड़ता है। जब कहा जाता है कि स्पैन को क्लिक किया जाता है, तो साझा एरे में सही तत्व को हटा दिया जाता है Array.splice()। साझा किया गया सरणी सही रूप से अपडेट किया गया है, लेकिन परिवर्तन दृश्य में परिलक्षित नहीं होता है। हालांकि, जब एक और तत्व जोड़ा जाता है, तो हटाने के बाद, दृश्य सही ढंग से ताज़ा हो जाता है और पहले हटाए गए तत्व को नहीं दिखाया जाता है।

मैं क्या गलत हो रहा हूँ? क्या आप मुझे समझा सकते हैं कि यह काम क्यों नहीं करता है? क्या वहाँ एक बेहतर तरीका है जो मैं AngularJS के साथ करने की कोशिश कर रहा हूं?

यह मेरा index.html है:

<!doctype html>
<html>
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.min.js">
        </script>
        <script src="main.js"></script>
    </head>
    <body>
        <div ng-app="livePlugins">
            <div ng-controller="pluginlistctrl">
                <span>Add one of {{pluginList.length}} plugins</span>
                <li ng-repeat="plugin in pluginList">
                    <span><a href="" ng-click="add()">{{plugin.name}}</a></span>
                </li>
            </div>
            <div ng-controller="k2ctrl">
                <div ng-repeat="pluginD in pluginsDisplayed">
                    <div k2plugin pluginname="{{pluginD.name}}" pluginid="{{pluginD.id}}"></div>
                </div>
            </div>
        </div>
    </body>
</html>

यह मेरा main.js है:

var app = angular.module ("livePlugins",[]);

app.factory('Data', function () {
    return {pluginsDisplayed: []};
});

app.controller ("pluginlistctrl", function ($scope, Data) {
    $scope.pluginList = [{name: "plugin1"}, {name:"plugin2"}, {name:"plugin3"}];
    $scope.add = function () {
        console.log ("Called add on", this.plugin.name, this.pluginList);
        var newPlugin = {};
        newPlugin.id = this.plugin.name + '_'  + (new Date()).getTime();
        newPlugin.name = this.plugin.name;
        Data.pluginsDisplayed.push (newPlugin);
    }
})

app.controller ("k2ctrl", function ($scope, Data) {
    $scope.pluginsDisplayed = Data.pluginsDisplayed;

    $scope.remove = function (element) {
        console.log ("Called remove on ", this.pluginid, element);

        var len = $scope.pluginsDisplayed.length;
        var index = -1;

        // Find the element in the array
        for (var i = 0; i < len; i += 1) {
            if ($scope.pluginsDisplayed[i].id === this.pluginid) {
                index = i;
                break;
            }
        }

        // Remove the element
        if (index !== -1) {
            console.log ("removing the element from the array, index: ", index);
            $scope.pluginsDisplayed.splice(index,1);
        }

    }
    $scope.resize = function () {
        console.log ("Called resize on ", this.pluginid);
    }
})

app.directive("k2plugin", function () {
    return {
        restrict: "A",
        scope: true,
        link: function (scope, elements, attrs) {
            console.log ("creating plugin");

            // This won't work immediately. Attribute pluginname will be undefined
            // as soon as this is called.
            scope.pluginname = "Loading...";
            scope.pluginid = attrs.pluginid;

            // Observe changes to interpolated attribute
            attrs.$observe('pluginname', function(value) {
                console.log('pluginname has changed value to ' + value);
                scope.pluginname = attrs.pluginname;
            });

            // Observe changes to interpolated attribute
            attrs.$observe('pluginid', function(value) {
                console.log('pluginid has changed value to ' + value);
                scope.pluginid = attrs.pluginid;
            });
        },
        template: "<div>{{pluginname}} <span resize>_</span> <span remove>X</span>" +
                       "<div>Plugin DIV</div>" +
                  "</div>",
        replace: true
    };
});

app.directive("remove", function () {
    return function (scope, element, attrs) {
        element.bind ("mousedown", function () {
            scope.remove(element);
        })
    };

});

app.directive("resize", function () {
    return function (scope, element, attrs) {
        element.bind ("mousedown", function () {
            scope.resize(element);
        })
    };
});

जवाबों:


131

जब भी आप AngularJS के बाहर किसी प्रकार का ऑपरेशन करते हैं, जैसे कि jQuery के साथ एक Ajax कॉल करना, या किसी ईवेंट को किसी ऐसे तत्व से बाँधना जैसे कि यहाँ आपको अपने आप को अपडेट करने के लिए AngularJS को बताना होगा। यहाँ कोड परिवर्तन आपको करने की आवश्यकता है:

app.directive("remove", function () {
    return function (scope, element, attrs) {
        element.bind ("mousedown", function () {
            scope.remove(element);
            scope.$apply();
        })
    };

});

app.directive("resize", function () {
    return function (scope, element, attrs) {
        element.bind ("mousedown", function () {
            scope.resize(element);
            scope.$apply();
        })
    };
});

यहाँ यह पर दस्तावेज़ीकरण है: https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$apply


4
$ लागू करने के लिए पारित एक अभिव्यक्ति / कार्य के अंदर दायरे (तत्व) और गुंजाइश.resize (तत्व) को आगे बढ़ाने पर विचार करें।
प्रति हॉर्न्सोज-शियरबेक

1
@ PerHornshøj-Schierbeck मैं सहमत हूं, अन्यथा यदि वे होते हैं तो कोणीय त्रुटियों के बारे में पता नहीं होगा।
जिम आहो

2
सावधान रहे ! आम तौर पर, कोणीय को पाचन चक्र कहते हैं जब उसे करना पड़ता है और $ एप इसे मैन्युअल रूप से कॉल करेगा। इसे मैन्युअल रूप से कॉल करने के लिए अक्सर एक बुरा अभ्यास होता है, क्योंकि हम अनुकूलन त्रुटियां कर सकते हैं, और यह संसाधन खपत हो सकता है।
एलेक्स

मुझे समझ में नहीं आ रहा है कि आप क्या कर रहे हैं या हटाएं।
डेसरोलो डेसाफियो डे गुएरेरो

53

यदि आप एक $scope.$apply();अधिकार जोड़ते हैं $scope.pluginsDisplayed.splice(index,1);तो यह काम करता है।

मुझे यकीन नहीं है कि ऐसा क्यों हो रहा है, लेकिन मूल रूप से जब एंगुलरजेएस को पता नहीं है कि $ गुंजाइश बदल गई है, तो इसे $ $ मैन्युअल रूप से कॉल करने की आवश्यकता है। मैं AngularJS में भी नया हूँ इसलिए इसे बेहतर नहीं समझा सकता हूँ। मुझे इसमें और अधिक देखने की जरूरत है।

मुझे यह भयानक लेख मिला जो इसे ठीक से समझाता है। नोट: मुझे लगता है कि "मूसडाउन" के लिए बाध्य करने के बजाय एनजी-क्लिक (डॉक्स) का उपयोग करना बेहतर हो सकता है । मैंने यहां एक सरल ऐप ( http://avinash.me/losh , source http://github.com/hardfire/losh ) AngularJS पर आधारित लिखा है । यह बहुत साफ नहीं है, लेकिन यह मदद का हो सकता है।


7

मेरी भी यही समस्या थी। समस्या इसलिए थी क्योंकि 'एनजी-कंट्रोलर' को दो बार (रूटिंग में और HTML में भी) परिभाषित किया गया था।



0

ऐसा करने का एक आसान तरीका है। बहुत आसान। जब से मैंने उस पर गौर किया

$scope.yourModel = [];

आप इस तरह से कर सकते हैं सभी $ गुंजाइश.yourModel सरणी सूची निकालता है

function deleteAnObjectByKey(objects, key) {
    var clonedObjects = Object.assign({}, objects);

     for (var x in clonedObjects)
        if (clonedObjects.hasOwnProperty(x))
             if (clonedObjects[x].id == key)
                 delete clonedObjects[x];

    $scope.yourModel = clonedObjects;
}

$ गुंजाइश.yourModel को क्लोन किए गए ऑबजेक्ट के साथ अपडेट किया जाएगा।

उम्मीद है की वो मदद करदे।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.