2

I'm trying to build a list of people with dividers for each letter (similar to a phone's address book).

people = ['Angela','Annie','Bob','Chris']; Result: A Angela Annie B Bob C Chris 

I want to do something similar to this pseudocode using Angular:

<div id="container" ng-init="lastCharacter = ''"> @foreach(person in people) @if(firstCharacter(person.name) != lastCharacter) <div class="divider-item">{{firstCharacter(person.name)}}</div> {{lastCharacter = firstCharacter(person.name)}} @endif <div class="person-item">{{person.name}}</div> @endforeach </div> 

What is the easiest way to achieve this? I couldn't come up with an elegant solution using ng-repeat.

2 Answers 2

1

You should create a custom filter and move the grouping logic inside that:

app.filter('groupByFirstLetter',function(){ return function(input){ var result = []; for(var i = 0;i < input.length; i++){ var currentLetter = input[i][0] var current = _.find(result, function(value){ return value.key == currentLetter; }); if(!current){ current = {key: currentLetter, items: []} result.push(current); } current.items.push(input[i]); } return result; }; }); 

Then the view gets simple:

 <div ng-repeat="personGroup in people | groupByFirstLetter"> <div class="divider-item">{{personGroup.key}}</div> <div class="person-item" ng-repeat="person in personGroup.items"> {{person}} </div> </div> 

Here's a little working example in plunker : http://plnkr.co/edit/W2qnTw0PVgcQWS6VbyM0?p=preview It's working but it throws some exceptions, you will get the idea.

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

2 Comments

Thank you for responding. This solution causes the "personGroup in people..." div to repeat for each letter group. Is there a solution that does not require a container? <div class="divider-item">A</div><div class="person-item">Angela</div><div class="divider-item">B</div><div class="person-item">Bob</div>
@KyleT I updated it with ng-repeat-start plnkr.co/edit/0v9tNtYcUgS6t5OBXUne?p=preview
1

try (use sorted list)

<div id="container" ng-repeat="person in people"> <div class="divider-item" ng-if="$index == 0 || ($index > 0 && firstCharacter(person.name) != firstCharacter(people[$index-1].name))">{{firstCharacter(person.name)}}</div> <div class="person-item">{{person.name}}</div> </div> 

hope, you have firstCharacter function defined in scope. Or you can simpley use person.name.charAt(0).

edit: as this will contain id container for all person. so best would be using an inner div inside container and run ng-repeat on there

<div id="container" > <div ng-repeat="person in people"> <div class="divider-item" ng-if="$index == 0 || ($index > 0 && firstCharacter(person.name) != firstCharacter(people[$index-1].name))">{{firstCharacter(person.name)}}</div> <div class="person-item">{{person.name}}</div> </div> </div> 

3 Comments

i have rewritten the ng-repeat part. please check
This causes the container to repeat with each person. I only need the container once.
you can wrap ng-repeat in a inner div

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.