Skip to content
Advertisement

Angular create element if another is non-existent

I have a list of states (Florida, Alabama …) and I want to create named anchors above the first occurance of the first letter.

Letter Links

  <nav>
    <ul class="letters">
      <li ng-repeat="letter in locations.getLetters()">
        <a href="#{{letter}}">{{letter}}</a>
      </li>
    </ul>
  </nav>

States

     <nav>
        <ul class="locations">
          <li ng-repeat="state in locations.states">{{state.state}}
            <a ng-if="" id="{{state.state.charAt(0)}}">fgsdf</a>
            <ul>
              <li ng-repeat="city in state.cities">
                <a href>{{city.name}}</a>
              </li>
            </ul>
          </li>
        </ul>
      </nav>

I am stuck at <a ng-if="" id="{{state.state.charAt(0)}}">fgsdf</a>

I have tried ng-if="!document.getElementById(state.state.charAt(0))" and that doesn’t work. Does anyone have any suggestions as to how I should go about this?

Update

I’ve considered using angular’s built-in filters to filter the states in ngRepeat. When a user clicks A, only the states starting with A should show. This seems like a much cleaner and more intuitive approach and will improve UX.

Advertisement

Answer

You can try this approach

let’s assume you have the input as a simple array of strings. before placing it in the controller, we can group states by the first letter of each state using a simple object (the letter is a key, the value is an array of strings)

http://jsfiddle.net/q2y93ym7/1/

html:

<body ng-app="HelloApp" ng-controller="Controller" class="container"> 
    <div class="well">
        <a href="#{{letter}}" ng-repeat="(letter,states) in letters">{{letter}} </a> 
    </div>
    
    <div ng-attr-id="{{letter}}" ng-repeat="(letter,states) in letters">
         <h1>{{letter}}</h1>
         <h2 ng-repeat="state in states">{{state}}</h2>
        <hr>
    </div>
</body>

js:

angular.module('HelloApp', [])
    .controller('Controller', function ($scope) {
    var states = ['Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorado', 'Connecticut', 'Delaware', 'Florida', 'Georgia', 'Hawaii', 'Idaho', 'Illinois Indiana', 'Iowa', 'Kansas', 'Kentucky', 'Louisiana', 'Maine', 'Maryland', 'Massachusetts', 'Michigan', 'Minnesota', 'Mississippi', 'Missouri', 'Montana Nebraska', 'Nevada', 'New Hampshire', 'New Jersey', 'New Mexico', 'New York', 'North Carolina', 'North Dakota', 'Ohio', 'Oklahoma', 'Oregon', 'Pennsylvania Rhode Island', 'South Carolina', 'South Dakota', 'Tennessee', 'Texas', 'Utah', 'Vermont', 'Virginia', 'Washington', 'West Virginia', 'Wisconsin', 'Wyomin'];

    // Let's prepare the input

    var letters = $scope.letters = {};
    states.forEach(function (state) {
        var letter = state.charAt(0);
        if (!letters[letter]) {
            letters[letter] = [];
        }

        letters[letter].push(state);
    });

})

EDIT:

  • As @DRobinson says, nothing guarantees keys of an Object will be sorted. therefore you can try using this great approach / instead an Object, use an array
  • added <h1>{{letter}}</h1>, thanks @Tony
Advertisement