3

I have an application that is using angular.js and I'm very new to it. I have a list of checkboxes that gets dynamically created based on a previous selection.

For example, if I have a dropdown of Fruits, the following html will get created:

<input type='checkbox' value="apple">apple</input>
<input type='checkbox' value="banana">banana</input>
<input type='checkbox' value="mango">mango</input>
<input type='checkbox' value="orange">orange</input>
<input type='checkbox' value="pear">pear</input>
<input type='checkbox' value="watermelon">water</input>

However, sometimes the amount of checkboxes that get generated gets more than 20 items, and I want to make use of some unused space.

So I was wondering if it's possible to split a list of checkboxes into two columns instead of one, so that a new column will generate filling up the rest of the checkboxes?

For example: If I have 18 items, instead of one large list of a single column containing 18 checkboxes, the final result will be to have 10 checkboxes in on column, and 8 checkboxes in another column next to it. I want to only have 2 columns as the maximum. Is this possible?

Here is what I have so far, I'm not sure if this is the best way of doing it. Otherwise I'll just make an answer for this question and mark it as such. Logic for splitting the data will be done in code-behind I guess.

example: http://jsfiddle.net/7843b/

Visual representation

  X  Apple         X  Pears
  X  Banana        X  Watermelon
  X  Mango
  X  Orange

The X represents a checkbox.

1
  • Not sure why I got voted down and been voted to close, please don't be brutal, make a comment, and I'll make it more clear. This is a legitimate question. Commented Dec 4, 2013 at 6:32

3 Answers 3

9

Seems like these solutions are a bit more complicated than needs to be. Let css handle putting them into columns:

Javascript:

$scope things = ["car", "box", "plant", "dice", "knife", "calendar"];

html:

<div  class="checkbox-column" ng-repeat='thing in things'>
    <input type="checkbox" /><span>{{thing}}</span>
</div>

in the css display each element with an inline-block and a width around 48%.

.checkbox-column{
    display: inline-block;
    width:48%; 
}

The width of 48% will give it 2 columns. If you want 3 columns, then just use a width of like 30%. This will also keep the columns aligned when the browser window is adjusted.

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

1 Comment

This won't keep the items in alphabetical order from top to bottom, but is sufficient if you want the items to be alphabetical from left to right.
3

Another way is to add column number to each team in the $scope.teams.

http://jsfiddle.net/dkitchen/y5UzD/4/

This splits them into groups of 10...

function TeamListController($scope) {

$scope.teams = [
    { name: "apple", id: 0, isChecked: true, col:1 }, 
    { name: "banana", id: 1, isChecked: false, col:1 }, 
    { name: "mango", id: 2, isChecked: true, col:1 },
    { name: "orange", id: 3, isChecked: true, col:1 }, 
    { name: "pear", id: 4, isChecked: false, col:1 }, 
    { name: "john", id: 5, isChecked: true, col:1 },
    { name: "paul", id: 6, isChecked: false, col:1 },
    { name: "george", id: 7, isChecked: true, col:1 },
    { name: "ringo", id: 8, isChecked: true, col:1 },
    { name: "roger", id: 9, isChecked: false, col:1 },
    { name: "dave", id: 10, isChecked: true, col:2 },
    { name: "nick", id: 11, isChecked: false, col:2 }
    ];
}   

You can do that at the data source, or you can assign the column number later in the controller.

For example, this bit re-groups them into 8 items per column:

var colCounter = 1;
var colLimit = 8;
angular.forEach($scope.teams, function(team){        

    if((team.id + 1) % (colLimit + 1) == 0) {
        colCounter++;
    }
    team.col = colCounter;

});

Then in the view, you can filter each repeater by column number:

<div ng-app>
<div ng-controller="TeamListController">
    <div class="checkboxList">
        <div id="teamCheckboxList">
            <div ng-repeat="team in teams | filter: { col: 1 }">
                <label>
                    <input type="checkbox" ng-model="team.isChecked" /> <span>{{team.name }}</span>

                </label>
            </div>
        </div>
    </div>
    <div>
        <div id="teamCheckboxList1">
            <div ng-repeat="team in teams | filter: { col: 2 }">
                <label>
                    <input type="checkbox" ng-model="team.isChecked" /> <span>{{team.name}}</span>
                </label>
            </div>
        </div>
    </div>

    </div>

2 Comments

Hey, I like this solution a lot, but just wondering, what would dictate the values to decide what should be in column 2? Would that be configured from the server side before hitting the angular page?
Sure... or if you want your data source to be unconcerned with column, this example shows the col property being added later in the controller: jsfiddle.net/dkitchen/y5UzD/5 You gotta love dynamic objects.
2

This is not so surprising question at all. You can dynamically add the items in either js or else you can do the same in html itself. I am here mentioning how to split dynamically based on the number of items.

function TeamListCtrl($scope) {
    $scope.teams = [
        { name: "apple", id: 0, isChecked: true }, 
        { name: "banana", id: 1, isChecked: false }, 
        { name: "mango", id: 2, isChecked: true },
        { name: "orange", id: 3, isChecked: true },
        { name: "pear", id: 4, isChecked: false }, 
        { name: "watermelon", id: 5, isChecked: true }
    ];

    column1 = [];
    column2 = [];
    $.each($scope.teams, function(index){
        console.log("index"+index);
        if(index%2==0) {
            column1.push($scope.teams[index]);
        } else{
            column2.push($scope.teams[index]);
        }
    });
    $scope.columns.push(column1);
    $scope.columns.push(column2);
}

And you can modify your html code as:

<div ng-app>
    <div ng-controller="TeamListCtrl" class="checkboxList">
        <div id="teamCheckboxList">
            <div ng-repeat='column in columns'>
                <div class='someClassToArrangeDivsSideBySide' ng-repeat="team in column">
                    <label>
                        <input type="checkbox" ng-model="team.isChecked" /> <span>{{team.name}}</span>
                    </label>
                </div>
            </div>
        </div>
    </div>
</div>

4 Comments

Hey that's better logic than what I anticipated. I tried to create a jsfiddle of it, but it doesn't work. I think I can try to figure it out using your logic as a base. One thing though, as I'm reading the code, it just seems that odd indexed checkboxes would appear on the left pane, and even indexed checkboxes would appear on the right pane. Is there any way I can have an ordered list that would simply populate one side first, then fill up the side next to it?
like if I have 8 items, instead of indexes 0, 2, 4, 6 go into one column.. 1, 3, 5, 7 go into the column next to it.. the items should be, 0, 1, 2, 3, 4 would go into one column, and 5, 6, 7 would populate the second.
I think the example above mixes in some jquery syntax, which might be why it doesn't work in jsfiddle (unless you enable jquery). Try this (no jquery): jsfiddle.net/dkitchen/y5UzD/4
Yes sksallaj, You can convert the code as per your requirements. I just showed you how we can achieve that in simple manner. If you want to have 1 to k items in first side and k+1 to n in the other side, then you can do this: Just simply, add if(index<k) in place of if(index%2), where k represents the number of items in first column

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.