Search code examples
javascriptangularjssortingangularjs-orderby

Sort user input alphabetically with AngularJS


I have built a simple Bootstrap-based form. The collected user input are displayed at the bottom of the page (thanks to AngularJS):

<script type="text/javascript" language="javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.8/angular.min.js"></script>
<link type="text/css" rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/css/bootstrap.min.css" />

<body ng-app>
<form>
  <fieldset class="border rounded">
  <legend class="alert alert-info">Keywords</legend>
    <div class="form-group row" id="IT-keywords">
      <label for="keywordsIT" class="col-auto col-form-label">Five <span class="badge badge-pill badge-warning">Italian</span> keywords:</label>
      <div class="col">
        <input type="text" class="form-control" name="keywordsIT" id="keywordsIT1" ng-model="keywordsIT1">
      </div>
      <div class="col">
        <input type="text" class="form-control" name="keywordsIT" id="keywordsIT2" ng-model="keywordsIT2">
      </div>
      <div class="col">
        <input type="text" class="form-control" name="keywordsIT" id="keywordsIT3" ng-model="keywordsIT3">
      </div>
      <div class="col">
        <input type="text" class="form-control" name="keywordsIT" id="keywordsIT4" ng-model="keywordsIT4">
      </div>
      <div class="col">
        <input type="text" class="form-control" name="keywordsIT" id="keywordsIT5" ng-model="keywordsIT5">
      </div>
    </div>
    <div class="form-group row" id="EN-keywords">
      <label for="keywordsEN" class="col-auto col-form-label">Five <span class="badge badge-pill badge-warning">English</span> keywords:</label>
      <div class="col">
        <input type="text" class="form-control" name="keywordsEN" id="keywordsEN1" ng-model="keywordsEN1">
      </div>
      <div class="col">
        <input type="text" class="form-control" name="keywordsEN" id="keywordsEN2" ng-model="keywordsEN2">
      </div>
      <div class="col">
        <input type="text" class="form-control" name="keywordsEN" id="keywordsEN3" ng-model="keywordsEN3">
      </div>
      <div class="col">
        <input type="text" class="form-control" name="keywordsEN" id="keywordsEN4" ng-model="keywordsEN4">
      </div>
      <div class="col">
        <input type="text" class="form-control" name="keywordsEN" id="keywordsEN5" ng-model="keywordsEN5">
      </div>
    </div>
  </fieldset>
</form>

<p>My five Italian keywords: {{keywordsIT1}}, {{keywordsIT2}}, {{keywordsIT3}}, {{keywordsIT4}}, {{keywordsIT5}}.</p>
<p>My five English keywords: {{keywordsEN1}}, {{keywordsEN2}}, {{keywordsEN3}}, {{keywordsEN4}}, {{keywordsEN5}}.</p>
</body>

I was wondering whether it would be possible to sort alphabetically the list of keywords after the user has typed them, so that if:

  • {{keywordsEN1}} = b, {{keywordsEN2}} = d, {{keywordsEN3}} = a, {{keywordsEN4}} = e, {{keywordsEN5}} = c

the result is:

  • a, b, c, d, e.

Any help will be greatly appreciated. Thank you all.


Solution

  • I would suggest you use arrays instead as they are easier to handle. This way all you need to do is sort the array and then join the elements in the array with a ,. I'm using filter to filter out all the null or undefined values before sorting so that they are omitted. Use localeCompare and convert your strings to lowercase during sort so that it will work correctly even if there are capital letters in your input.

    Also, since Italian words contain accents/diacritics (Eg. è or ò), you will need to normalize the input before you sort the array.

    Here is a working example.

    angular.module('app', [])
      .controller('ctrl', ['$scope', ($scope) => {
        $scope.keywordsIT = new Array(5);
        $scope.keywordsEN = new Array(5);
    
        $scope.sortKeywordsIT = function() {
          return $scope.keywordsIT
            .filter(keyword => !!keyword)
            .map(keyword => keyword.normalize("NFD"))
            .sort((k1, k2) => k1.toLowerCase().localeCompare(k2.toLowerCase()))
            .join(', ');
        }
    
        $scope.sortKeywordsEN = function() {
          return $scope.keywordsEN
            .filter(keyword => !!keyword)
            .sort((k1, k2) => k1.toLowerCase().localeCompare(k2.toLowerCase()))
            .join(', ');
        }
      }]);
    <script type="text/javascript" language="javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.8/angular.min.js"></script>
    <link type="text/css" rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/css/bootstrap.min.css" />
    
    <body ng-app="app" ng-controller="ctrl">
      <form>
        <fieldset class="border rounded">
          <legend class="alert alert-info">Keywords</legend>
          <div class="form-group row" id="IT-keywords">
            <label for="keywordsIT" class="col-auto col-form-label">Five <span class="badge badge-pill badge-warning">Italian</span> keywords:</label>
            <div class="col">
              <input type="text" class="form-control" name="keywordsIT" id="keywordsIT1" ng-model="keywordsIT[0]">
            </div>
            <div class="col">
              <input type="text" class="form-control" name="keywordsIT" id="keywordsIT2" ng-model="keywordsIT[1]">
            </div>
            <div class="col">
              <input type="text" class="form-control" name="keywordsIT" id="keywordsIT3" ng-model="keywordsIT[2]">
            </div>
            <div class="col">
              <input type="text" class="form-control" name="keywordsIT" id="keywordsIT4" ng-model="keywordsIT[3]">
            </div>
            <div class="col">
              <input type="text" class="form-control" name="keywordsIT" id="keywordsIT5" ng-model="keywordsIT[4]">
            </div>
          </div>
          <div class="form-group row" id="EN-keywords">
            <label for="keywordsEN" class="col-auto col-form-label">Five <span class="badge badge-pill badge-warning">English</span> keywords:</label>
            <div class="col">
              <input type="text" class="form-control" name="keywordsEN" id="keywordsEN1" ng-model="keywordsEN[0]">
            </div>
            <div class="col">
              <input type="text" class="form-control" name="keywordsEN" id="keywordsEN2" ng-model="keywordsEN[1]">
            </div>
            <div class="col">
              <input type="text" class="form-control" name="keywordsEN" id="keywordsEN3" ng-model="keywordsEN[2]">
            </div>
            <div class="col">
              <input type="text" class="form-control" name="keywordsEN" id="keywordsEN4" ng-model="keywordsEN[3]">
            </div>
            <div class="col">
              <input type="text" class="form-control" name="keywordsEN" id="keywordsEN5" ng-model="keywordsEN[4]">
            </div>
          </div>
        </fieldset>
      </form>
      <p>My five Italian keywords: {{sortKeywordsIT()}}.</p>
      <p>My five English keywords: {{sortKeywordsEN()}}.</p>
    </body>