Is there a way to selectively include a filter in ng-repeat within a directive?

Utilizing an element directive across multiple views, the directive iterates through each 'resource' in a list of resources using

ng-repeat="resource in resources"
.

Different page controllers determine which resources are fetched from the API by having a unique $scope.resourceApiPath in each view controller. The directive controller then uses this path to make an $http call.

This setup works effectively for displaying different types of resources on different views - such as the user's own resources, public resources, and starred resources.

The challenge arises when I want to include a filter on the ng-repeat in one specific view:

ng-repeat="resource in resources | filter:resourceSearch.text"
. Is it possible to conditionally add this filter based on a variable like $scope.filter == true;, otherwise default to
ng-repeat="resource in resources"
?

Here is my directive:

.directive('resourcePanel', function() {
    return {
        restrict: 'E',
        scope: false,
        templateUrl: 'scripts/templates/resource-panel.html',
        controller: 'ResourcesPanelController'
    }
})

The ResourcesPanelController referenced in the directive includes code similar to this:

$scope.resources = [];
$scope.loadResources = function() {
    $scope.resources = []; // Clear array
    $http.get('/api/resource' + $scope.resourceApiPath)
        .then(function(res) {
            $scope.resources = res.data.message;
        });
};
$scope.loadResources();

The template

scripts/templates/resource-panel.html
looks something like this:

<div class="panel" ng-repeat="resource in resources">
    {{resource.content}}
</div>

Thank you!

Answer №1

There are multiple ways to approach this issue, but I personally recommend options 1 and 3. The best choice for you will depend on your specific requirements and coding standards.

A custom filter is also a great solution to consider.

  1. If you are using text values for filtering, not setting the value of resourceSearch.text essentially means no filter. If resourceSearch.text exists, it will apply the filter; if it's undefined, there will be no filter applied.

    ng-repeat="resource in resources | filter:resourceSearch.text"

  2. You can create a custom filter and manage the functionality there.

If you decide to go with a custom filter, make sure to utilize an enable argument that allows you to toggle the filter on and off. Here is a helpful example using Plunker: http://plnkr.co/edit/ilPJPUZkBC7Y5OvGHWey?p=preview. This Plunker features a custom filter that may meet your needs.

ng-repeat="resource in resources | customfilter:resourceSearch.text:enable"
  1. You can filter your final resources within the controller and then pass the filtered results to the HTML template.

  2. Another option is to use ng-if based on your condition - utilizing one loop if the filter exists and another loop if it does not.

I hope this information proves useful for you!

Answer №2

To implement a personalized filtering function, you can create the following:

$scope.customizedFilter = function(item) {
    if (!$scope.filterCriteria) {
        return true;
    }

    // Insert your specific filter conditions here
    return item.description.indexOf($scope.searchText) >= 0;
};

Next, utilize this custom filter in your template:

<div class="panel" ng-repeat="item in items | filter:customizedFilter">
    {{item.description}}
</div>

Answer №3

<div ng-if="!filter" class="panel" ng-repeat="resource in resources">
    {{resource.content}}
</div>
<div ng-if="filter" class="panel" ng-repeat="resource in resources| filter:resourceSearch.text">
    {{resource.content}}
</div>

My apologies for the lack of description, I tend to use this format when I believe it appears only once, as it looks more organized when flattened.

<div ng-if="!filter" class="panel" ng-repeat="resource in resources">{{resource.content}}</div>
<div ng-if="filter" class="panel" ng-repeat="resource in resources|filter:resourceSearch.text">{{resource.content}}</div>

If you prefer a more comprehensive solution, consider setting up a custom filter and inject 'filter'.

app.filter('conditionalFilter', function (filter) {
  return function (item, condition) {
    if(condition){
       return filter.bind(this,item).apply(this,[].slice.call(arguments,2));
    } else{ return item }
  };
});

And then:

<div class="panel" ng-repeat="resource in resources| conditionalfilter : !!filter : researchSearch.text" >
    {{resource.content}}
</div>

I have not tested this yet, so please let me know if there are any errors.

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

Accordion featuring collapsible sections

Looking to build an accordion box using Javascript and CSS. The expanded section should have a clickable link that allows it to expand even further without any need for a vertical scroll bar. Any ideas on how this can be achieved? Thank you ...

What is the best way to create floating text that appears when clicked, similar to the mechanics

https://i.stack.imgur.com/nRKG1.jpg Upon clicking the "big cookie" in my game, a popup appears displaying the number of cookies earned (like +276.341 septillion in this image). The popup slowly moves upward and then fades out. I successfully incorporated ...

Modifying the value of a property in one model will also result in the modification of the same

As a beginner with Vue, I am looking to allow users to add specific social media links to the page and customize properties like text. There are two objects in my data - models and defaults. The defaults object contains selectable options for social media ...

How can you sort an array based on a shared object property using Angular.js?

I've been grappling with this issue for a while now. My app receives data about individuals in JSON format: "people": [ { "name": "Ivan", "city": "Moscow", "country": "Russia" }, { "name": "John", ...

Can JavaScript be used to continuously monitor a window variable object in real-time?

Is there a way to dynamically control a variable in JavaScript? I'm currently working on a code that needs to display a button when it reaches the last signature of an automatic request process. The code for activating/deactivating the button is show ...

Tips for retrieving the tenth document in Firestore Query using JavaScript

Specifically, a selection of the arranged files. Here's my thought, although I know it can be improved: firestore().collection("queue").orderBy("order_id", "asc").limit(3,5) If anyone has a better solution, I would appre ...

Can a variable be declared within the path references of the Firebase database?

In an effort to update my app's database references, I am working on implementing specific Firebase rules that involve adding buildings and depts nodes inside the user node. This decision was prompted by a discussion on best practices for writing Fire ...

The initialization of the Angular service is experiencing issues

I have a service in place that checks user authentication to determine whether to redirect them to the login page or the logged-in area. services.js: var servicesModule = angular.module('servicesModule', []); servicesModule.service('login ...

Ways to showcase every resource from an API in React JS

I need help with adding code to display products along with their images from an API in my existing code. Can someone assist me with this? import React, {useState, useEffect} from 'react' import "bootstrap/dist/css/bootstrap.min.css" im ...

problem with accessing a website input area

Upon clicking outside the "subheader", I need to display the words "register" and "login" again, unless something is typed into the input fields... that's all there is to it, just click outside the subheader $(document).ready(function() { $(&ap ...

ReactJS mixes up fetch URLs with another fetch_WRONG_FETCH

I have a fetch function in my Home component: export default function Home() { const { rootUrl } = useContext(UserContext); useEffect(() => { fetch(`${rootUrl}/api/products/featuredProducts`) .then((result) => result.json()) .then ...

Selecting options on hover, either A or B at the least

I need a jQuery selector to handle an 'either' scenario. Specifically, I have a dropdown menu and want it to stay open when the user hovers over either of two elements. Either when they hover over the button or when they leave the popped-out men ...

Exploring the power of ng-change and ng-model within a custom directive - unraveling the inner workings of

Currently, I am developing a date picker for incorporating a range selector in AngularUI. To invoke a custom time picker in HTML, use the following code: <time-range name-time="Hours" max-length="2" min="00" max="23" step="01" ...

How to update JSON file on server using JavaScript

I am encountering an issue that has been discussed quite frequently. Despite trying various solutions, none have proven effective so far. The problem lies in my JavaScript file where I have some data that I need to append to an existing .json file on my s ...

JS/Apps Script: Passing object and its keys as function parameters

When working with Google Apps Script, I have a specific task that involves looping through data and writing only certain keys to a sheet. I want this looping operation to be done in a separate function rather than directly in the main function, as it will ...

What benefits does JavaScript offer with the strategy of storing functions within variables?

Lately I've come across some code where functions are being stored inside variables and then called in the typical way. For example: var myFunctionName = function() { Code Here... } myFunctionName(); I'm aware that there may be numerous b ...

Passing a MySQL connection to scripts in Express

After setting up the mysql connection with all the required parameters in app.js, is there a way to make it accessible to other scripts in routes/ without having to redeclare or require the mysql parameters again, simply by using client.query(..)? ...

Declare `document.body` as the designated container element for the material-ui Tooltip

The issue: I need to show a tooltip pointing to an element (referenceEl) from the left. The referenceEl is located within a container that has a limited width of 60px and has the css properties overflow: hidden applied. Due to the tooltip being appended af ...

I want to create a feature where a video will automatically play when a user clicks on a specific item in a list using Angular

Currently, I'm working on a project that involves displaying a list of videos and allowing users to play them in their browser upon clicking. The technology stack being used is Angular 2. Below is the HTML code snippet for achieving this functionalit ...

Upon running the command "React + $ npm start," an error occurred with the code 'ERR_OSSL_EVP_UNSUPPORTED' related to opensslErrorStack

When running $npm start, an error is being thrown: opensslErrorStack: [ 'error:03000086:digital envelope routines::initialization error' ], library: 'digital envelope routines', reason: 'unsupported', code: 'ERR_OSSL_EVP_ ...