AngularJS: Как да промените стойност във всички елементи в ng-repeat

Имам модел на данни, който идва, по подразбиране давам на първия тикер избран статус на true.

Сега, когато потребител щракне върху друг елемент, трябва ефективно да демаркирам всички останали и да задам избраната стойност на true за щракнатия елемент:

<li class="ticker-li"
    ng-repeat="ticker in tickers"
    ng-hide="ticker.removed"
    ng-class="{'selected':ticker.selected}"
    ng-mouseleave="hideTickerOptions()">

    <div class="ticker"
         ng-click="unselectAll(); ticker.selected = !ticker.selected;
                   selectTicker(ticker);">
         {{ticker.ticker}}
    </div>
</li>

Опитах функция forEach тук, но с грешка [object Array] is not a function:

var vs = $scope;

vs.unselectAll = function() {
   vs.tickers.forEach(vs.tickers, function(ticker) {
       ticker.selected = false;
   });
};

Обикновеният for-цикъл ще работи, но дали е ефективен начин за превключване на всички избрани стойности на false?

for (var i = 0; i < vs.tickers.length; i++) {
    vs.tickers[i].selected = false;
}

Моето мислене тук е да изпълня тази функция unselectAll, за да демаркирам всичко, след това следващия код в маркирането, който избира текущия елемент:

<div class="ticker"
     ng-click="unselectAll(); ticker.selected = !ticker.selected;
               selectTicker(ticker);">
     {{ticker.ticker}}
</div>

person Leon Gaban    schedule 04.05.2015    source източник


Отговори (3)


Опитах се да го направя с помощта на радио входове.

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

app.controller('ctrForm', function ($scope) {

        $scope.choices = [
            { id: 'Choice1', check: false },
            { id: 'Choice2', check: false },
            { id: 'Choice3', check: false },
            { id: 'Choice4', check: false },
            { id: 'Choice5', check: false },
            { id: 'Choice6', check: false },
            { id: 'Choice7', check: false }
        ];

        $scope.setDefault = function (item) {
            angular.forEach($scope.choices, function (p) {
                p.check = false; //set them all to false
            });
            item.check = true; //set the clicked one to true
        };
        
    });
.selected {
        background-color: yellow;
    }
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.21/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

<div ng-app="AppForm" ng-controller="ctrForm">
        <ul>
            <li style="list-style:none" ng-class="{'selected':item.check}" ng-repeat="item in choices"><input type="radio" name="group" ng-model="item.check" ng-click="setDefault(item)" value="true" />{{item.id}}...{{item.check}}</li>
        </ul>
    </div>

person Bruno Gomes    schedule 04.05.2015
comment
Приятно :) благодаря за работния пример... Всъщност използвах for-loop, но ще тествам това по-късно, за да видя дали има разлика в производителността. - person Leon Gaban; 05.05.2015
comment
Съжалявам, днес забелязах, че има малък бъг. Ако намерите решение, кажете ми. :) - person Bruno Gomes; 05.05.2015

Foreach не би бил по-малко ефективен от всичко, което angular може да направи „безплатно“. Така или иначе ще трябва да зададе другите като неизбрани..

Това, което бих предложил вместо това, е да има едно нещо "selectedItem" и набор от неща "items".

тогава можете да "кажете"

<li class="ticker-li"
    ng-repeat="ticker in tickers"
    ng-hide="ticker.removed"
    ng-class="{'selected':ticker == selectedTicker}"
    ng-mouseleave="hideTickerOptions()">

    <div class="ticker" ng-click="selectedTicker = ticker">
         {{ticker.ticker}}
    </div>
</li>

след това можете да получите достъп до selectedTicker, за да получите неговите свойства

<div>{{selectedTicker.name}}</div>
person Charlie Wynn    schedule 04.05.2015
comment
Хм, това все още оставя избрани всички предварително избрани тикери. - person Leon Gaban; 04.05.2015
comment
ще остави избрания, но си мисля, че вместо да проверявате за isSelected, ще проверите дали са равни на „selectedTicker“ (вижте маркера ng-class в моя код) - person Charlie Wynn; 04.05.2015
comment
Да, това е основно същото като това, което използвах ng-class="{'selected':ticker.selected}" Просто имам нужда от начин да актуализирам модела, за да премахна или променя selected или selectedTicker от всички елементи, преди да избера отново. - person Leon Gaban; 04.05.2015
comment
Това, което предлагах, беше да се избягва настройката, избрана за всеки елемент. Вместо това задайте нов обект към избрания всеки път, когато промените селекцията. След това, за да разберете дали е избран тикер, можете просто да проверите дали е равен на избрания тикер. По този начин не е необходимо да преглеждате всички тикери, когато промените своя избор. - person Charlie Wynn; 04.05.2015

Ако сте задали да използвате ticker.selected, можете да използвате jquery .each цикъл, за да премахнете избора от всички тях.

$scope.selectTicker = function(ticker)
{
  //deselect all tickers
  $.each(tickers, function() { this.selected = false; });

  //select the ticker you passed in
  ticker.selected = true;
}

и според вас:

<div class="ticker"ng-click="selectTicker(ticker);">
     {{ticker.ticker}}
</div>
person Charlie Wynn    schedule 04.05.2015
comment
Определено искам да избягвам използването на jQuery, разчитах на него като на патерица, докато учех Angular. Мисля, че започва да изглежда, че for-loop е най-лесният начин да направите това. - person Leon Gaban; 04.05.2015
comment
Когато хората казват да не използват jquery с angular, те имат предвид да не използват нещата за манипулиране на DOM на jquery. Не че трябва да избягвате целия JQuery. Както и да е: angular има foreach, който работи точно по същия начин docs.angularjs.org/api /ng/function/angular.forEach - person Charlie Wynn; 04.05.2015
comment
Да, моето мислене обаче е да поддържам приложението възможно най-леко, така че да са необходими най-малко изтегляния за потребителя. Опитах Angular forEach по-горе, но с грешки :( - person Leon Gaban; 04.05.2015
comment
Наистина се занимавах с това известно време (запазих го леко), но реалистично, ако се свържете към минимизиран източник на jquery, това няма да забави ни най-малко потребителя в сравнение с изтеглянето на действителното ви приложение от вашия сървър. - person Charlie Wynn; 04.05.2015