Sort ng-repeat based on the initial character

Working in AngularJS, I am handling an array of objects and aiming to display filtered data based on the first letter. My initial method used was as follows. HTML:

<p ng-repeat="film in filmList | startsWith:'C':'title'">{{film.title}}</p>

JS:

.filter('startsWith', () => {
    return (items: any, prefix: any, itemProperty: any) => {
        if (items && items.length) {
            return items.filter((item: any) => {
                var findIn = itemProperty ? item[itemProperty] : item;
                return findIn.toString().indexOf(prefix) === 0;
            });
        }
    };
});`

Although this approach achieved success, my current objective is to filter (always considering the first letter) based on dual options. For instance, filtering movies with titles commencing with 'B' or 'C'.

I attempted the following code adjustment, which unfortunately did not produce the desired outcome:

HTML:

 <p ng-repeat="film in filmList | startsWith:'[B, C]':'title'">{{film.title}}</p>

JS:

.filter('startsWith', () => {
    return (items: any, prefixes: any, itemProperty: any) => {
        if (items && items.length) {
        return items.filter((item: any) => {
            var findIn = itemProperty ? item[itemProperty] : item;
            for(let i = 0; i < prefixes.length; i++){
                return findIn.toString().indexOf(prefixes[i]) === 0;
            }
        });
    }
    };
 });

Answer №1

If you're looking for a simpler solution that doesn't require an extra filter directive:

var app = angular.module("MyApp", []).controller("MyCtrl", function($scope) {

  $scope.filmList = [{
    title: "Spiderman"
  }, {
    title: "Titanic"
  }, {
    title: "Jurassic Park"
  }];

  $scope.customfilter = function(film) {
    return film.title.charAt(0) === 'S' || film.title.charAt(0) === 'T';
  };

});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<body ng-app="MyApp" ng-controller="MyCtrl">
  <p ng-repeat="film in filmList | filter: customfilter">{{film.title}}</p>
</body>

Answer №2

'[B, C]' as a parameter will be interpreted as a string rather than an array. It is recommended to define the array in the controller and then transform it accordingly.

UPDATE:

If you use return inside a for-loop, the loop will terminate. Changes have been made to prevent this scenario.

See the updated code snippet below:

var app = angular.module("app", [])
app.controller("myCtrl", function($scope) {
  $scope.filmList = [{
      title: 'Black'
    },
    {
      title: 'Brown'
    },
    {
      title: 'Clown'
    },
    {
      title: 'Red'
    },
    {
      title: 'Gray'
    }
  ];
  $scope.option = ['B', 'C'];
})
app.filter('startsWith', () => {
  return (items, prefixes, itemProperty) => {
    if (items && items.length) {
      return items.filter((item) => {
        var findIn = itemProperty ? item[itemProperty] : item;
        
        for (let i = 0; i < prefixes.length; i++) {
          if (findIn.toString().indexOf(prefixes[i]) === 0) {
            return true;
          }
        }
      });
    }
  };
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<div ng-app="app" ng-controller="myCtrl">
  <p ng-repeat="film in filmList | startsWith:option:'title'">{{film.title}}</p>
</div>

Answer №3

An alternative approach to preserving the option within the controller is by converting a string into an array. Let's say we have the following usage of ng-repeat:

<tr ng-repeat="x in names | startsWith:'B, C':'name'">

To create the array in the filter, we can do prefixes = prefixes.split(","). It would look something like this:

app.filter('startsWith', function() {
  return function(items, prefixes, itemProperty) {
    if (items && items.length) {
      prefixes = prefixes.split(",")
      return items.filter(function(item) {
        var findIn = itemProperty ? item[itemProperty] : item;
        for(var i = 0; i < prefixes.length; i++){
          if(findIn.toString().indexOf(prefixes[i].trim()) === 0) {
            return true
          }
        }
        return false
      });
    }
  };
});

Take note of using .trim() to eliminate any extra spaces.

Check out the live example

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Loading state with suggestions from autocomplete feature on React

In my current project, I have a component that consists of input fields and a button. The button is set to be disabled until the correct values are entered in the input fields. Everything works as expected, but there's an issue with Chrome auto-fillin ...

What is the recursive process for printing the numbers 1 to 5 and then 5 to 1?

I was looking to print numbers from 5 to 0 and then from 0 to 5 in the most concise way possible. The code I came up with is below. However, I am open to other suggestions that may require fewer lines of code. Looking forward to your feedback. Thanks! ...

Using jQuery to delay hiding for 2 seconds

Hey there! I'm facing an issue with my code. The function is supposed to make #aboutPopOut slide to the left, and then after a 2-second delay, fade out the fadescreen by hiding it. The sliding part works fine, but the waiting and hiding do not seem to ...

Using AngularJS: Setting a default value for the select option when the current selection is not valid

I am currently working on a cascading select feature where the value in the first dropdown determines the options available in subsequent dropdowns. However, when I change the value in the first dropdown and the previously selected option is no longer val ...

Having trouble with Semantic UI Modal onShow / onVisible functionality?

Seeking assistance with resizing an embedded google map in a Semantic UI modal after it is shown. After numerous attempts, I have narrowed down the issue to receiving callbacks when the modal becomes visible. Unfortunately, the onShow or onVisible functio ...

The jQuery focusout event is triggered on a form element, even if a child element is clicked within the form

How can I ensure that the focusout event is triggered only when the user is not focusing on the entire form element? Currently, if the user clicks on any of the form's inner elements such as the text field or the button, the event is still being trigg ...

Error: React JS is unable to access the property 'path' because it is undefined

Currently, I am encountering an issue while setting the src of my image in React to this.props.file[0].path. The problem arises because this state has not been set yet, resulting in a TypeError: Cannot read property 'path' of undefined. To provid ...

Retrieve information from XML using jQuery

<?xml version="1.0" encoding="UTF-8"?> <slider> <csliderData1> <title>Kung Fu Panda</title> <content>In the Valley of Peace, Po the Panda finds himself chosen as the Dragon Warrior despite</content ...

Using jQuery to load content with a dynamic variable instead of specific element IDs

I am facing a minor jQuery issue. I am trying to load a specific area of an external HTML document into a div, but instead of loading just that particular area, the entire document is being loaded. Here's the code snippet for the trigger: $('a& ...

Issue: There is no specified method of transportation established

I'm facing an issue while trying to create an Outlook calendar event from my application using Express.js. The error message I am receiving is [Error:No transport method defined], and eventually, the response returns as 200 success after approximately ...

Modifying script variables using the Chrome console

There is a button on the website that looks like this: https://i.sstatic.net/G7PBF.png Clicking on this button triggers the following script: https://i.sstatic.net/rIdLW.png function count(){ let downloadTimer; var timeleft = 30; downloadTimer = setInte ...

Determine if the start_date is greater than the end_date using jQuery

Having a particular issue with date validation. The start_date and end_date are obtained from an HTML form, being chosen using a bootstrap date picker. A sample of the dates looks like this: start_date = 15-06-2016 end_date = 14-06-2016 To verify if th ...

Issue with selecting multiple items in DataTables using the shift key

Currently, I am working with datatable 1.10 and have successfully created a table. However, I am unable to enable the multiple "shift select" functionality for its rows. Referring to the official DataTables documentation: The TableTools plugin offers fou ...

When attempting to register a custom Gamepad class using GamepadEvent, the conversion of the value to 'Gamepad' has failed

I have been working on developing a virtual controller in the form of a Gamepad class and registering it. Currently, my implementation is essentially a duplicate of the existing Gamepad class: class CustomController { readonly axes: ReadonlyArray<nu ...

Optimal approach to displaying views with Express.js and EJS

Recently, I came across a website that only renders EJS templates using Express.js routing. All the routes are defined in the /routes/index.js file. As the file grows with more routes being added, I am thinking about restructuring it to make it more develo ...

Show real-time server responses using jQuery while waiting for the AJAX request to complete

I have a challenge in creating a function that displays the server response while waiting for Ajax to complete. Here's the scenario: I have selected 10 checkboxes. When I click the submit button, Ajax is triggered. On the server side, there is a loo ...

Using JavaScript and AJAX to manage and control a shell interface

Looking to create an HTML page that includes a YouTube video and utilizes JavaScript with the YouTube API. The objective is to embed a video and test if it has been fully downloaded using the YouTube API. I have set up an Apache server with MySQL and PHP ...

Techniques for retrieving user inputs upon loading the HTML document and detecting changes using JavaScript

I am new to using JS to pass data to Python. I have managed to collect the values when the HTML is loaded, but I am facing an issue where the value does not change when it is updated. Here is the code snippet that I have been working with: <input type= ...

Concealing the parent template in Vue Router when the child is displayed

Having some trouble setting up Vue.js with the router, specifically dealing with view display issues. I've created a router.js file with child routes for breadcrumbs and route clarity purposes. Each individual route loads perfectly fine when opened. ...

Split the string into individual parts and enclose each part in HTML using JavaScript

Currently, I am utilizing a content editable div to create tags. Upon pressing the return key, my objective is to select the preceding text (excluding the prior tags) and transform it into a new tag. The format for a tag will be enclosed within . For insta ...