0

In my Angular app, I have the following list of checkboxes, generated within a nested ng-repeat:

<div ng-repeat="type in boundaryPartners">
    <div class="row" ng-show="showBPtype[$index]">
        <div class="col-xs-12">
            <div ng-repeat="partner in type.partners">
                <label class="checkbox-inline">
                    <input type="checkbox"
                        value="partner.id"
                        ng-model="partner.selected"
                        ng-change="changeValue(partner)"
                        />
                    <p><span ></span>{{partner.name}}<p>
                </label>
            </div>
        </div>
    </div>
</div>

This list is retrieved from a data and has the following structure (sample):

{
    "id": 1,
    "name": "Civil Society Organizations",
    "partners": [{
        "id": 1,
        "name": "Youth Association"
    }, {
        "id": 2,
        "name": "Rwanda Network"
    }, {
        "id": 3,
        "name": "Communité du Rwanda"
    }]
},

{
    "id": 2,
    "name": "Educational Organizations",
    "partners": [{
        "id": 16,
        "name": "SchoolA"
    }, {
        "id": 17,
        "name": "SchoolB"
    }]
}

This is an array of objects, which represent the type of partner, which each contain a list of partners of that time, within the array partners.

This will end up looking like the picture below:

enter image description here

When a user selects a partner with a chekcbox, this partner is supposed to get added to a nested list of selected partners (following a similar structure), and when a user deselects a checkbox, that partner is to be deleted.

I already have a working solution for a single list of partners which was provided by user Artyom Pranovich in his answer (all credit to him).

This is his code:

var partnersList = [], idsArray = [];

$scope.changeValue = function(partner){
   if(partner.selected)
      addPartner(partner);
   else
      removePartner(partner);
};

var addPartner= function(partner){
    if(!existInList(partner))
       partnersList.push(partner);
};

var removePartner= function(partner){
    idsArray = getIdsArray();
    var indexToRemove = idsArray.indexOf(partner.id);
    if(indexToRemove == -1)
       return;

    partnersList.splice(indexToRemove, 1);
};

var existInList = function(partner){
    idsArray = getIdsArray();
    return idsArray.indexOf(partner.id) != -1;
};

var getIdsArray = function(){
    return partnersList.map(function(partner){ return partner.id });
};

However, using the interface I described above, I need to populate a nested list of partners, containing only the partners which where selected by the user, with the same structure as the one I described before: a list of partner objects, organized by type (which has an type.id number and a type.partners array).

I've tried some solutions using $parent.$index and $index to locate which partner I should be adding/removing when necessary, but I can't seem to wrap my head around this.

What would be the best way to adapt the suggested code to my needs?

EDIT: adding the structure of the final list containing the selected partners (i. e. the list where partners will have to get pushed to), as requested. Sample:

[
    {
        "id": 1,
        "entities": [
            {
                "id": 2,
                "name": "Entity 2"
            },
            {
                "id": 3,
                "name": "Entity 3"
            }
        ]
    },
    {
        "id": 2,
        "entities": [
            {
                "id": 2,
                "name": "Entity 2"
            }
        ]
    }
]

Within the app, this list is called $scope.report.participatingPartners.

9
  • Could you publish your not working app? Commented Sep 29, 2015 at 12:36
  • Pls, provide example of your desired json structure (which will contain already selected partners). It's unclearly, where you want to add selected partners. Commented Sep 29, 2015 at 12:43
  • The structure of selected partners will be the same as the initial list of partners used to populate the ng-repeat, as you can see on the second block of code. Commented Sep 29, 2015 at 12:50
  • @Tiago, not exactly what I want to know. Where this list of selected partners is loсated in relation to the type object from $scope.boundaryPartners? It will be included into the object from partners array? Commented Sep 29, 2015 at 13:07
  • They are 2 different objects, because one contains a list of all partners ($scope.boundaryPartners), while the other will contain only the list of selected partners ($scope.report.participatingPartners). Commented Sep 29, 2015 at 13:12

1 Answer 1

1

If I've understood your problem, the solution will be similar with it.

If you have questions, don't hesitate to ask.

<div ng-repeat="organization in boundaryPartners">
    <div ng-repeat="partner in organization.partners">
        <label>
            <input type="checkbox" value="partner.id" ng-model="partner.selected" 
                   ng-change="changeValue(partner, organization, $parent.$index)"/>
            {{partner.name}}
        </label>
    </div>
    <hr/>
</div>

$scope.participatingPartners = []
var idsArray = [];

$scope.changeValue = function(partner, organization, index){
   if(partner.selected)
      addPartner(partner, organization, index);
   else
      removePartner(partner, organization, index);
};

var addPartner= function(partner, organization, index){
    prepareArrayToAdd(organization, index);
    if(!existInList(index, partner)){
        $scope.participatingPartners[index].partners.push(partner);
    }
};

var prepareArrayToAdd = function(organization, index){
    if(!$scope.participatingPartners[index])
        $scope.participatingPartners[index] = { id: organization.id, name: organization.name, partners: [] };
};

var removePartner= function(partner, organization, index){
    idsArray = getIdsArray(index);
    var indexToRemove = idsArray.indexOf(partner.id);
    if(indexToRemove == -1)
       return;

    $scope.participatingPartners[index].partners.splice(indexToRemove, 1);
};

var existInList = function(index, partner){
    idsArray = getIdsArray(index);
    return idsArray.indexOf(partner.id) != -1;
};

var getIdsArray = function(index){
    return $scope.participatingPartners[index].partners.map(function(partner){ return partner.id });
};

JSFIddle link.

Hope it helps!

Sign up to request clarification or add additional context in comments.

2 Comments

reformatArrayAfterRemove() seems to be missing though.
@Tiago. This function is a redundant, see JSFiddle for live demo. I've updated code in the answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.