Exploring Angular's ng-model and filter capabilities with nested data compared to top layer data structures

On my webpage, I have a list of data presented in divs. Each div corresponds to an array of data in my object, which is a common setup.

I am currently working on implementing a text box that will allow me to filter the displayed data as more information is entered into the box. This way, users can quickly narrow down the results shown on the page.

To enable this filtering functionality, I have added a filter to my ngFor directive:

*ngFor="let x of data | filter: filterString"
.

The text-box utilizes ngModel to handle the filtering:

<input type="text" class="form-control" placeholder="Filter..." name="ruleFilter" id="ruleFilter" [(ngModel)]="filterString" (keyup)="onFilter($event)">

However, I am running into an issue where the filter only seems to be effective on the top layer of data within my object. For instance, searching for Omaha works fine because it's at the top level and gets filtered correctly.

But when attempting to search for something like Campus, which is nested inside Attribute, the filter doesn't recognize it, resulting in no matching results being displayed.

Is there a way to configure the model to search through all layers of the object for binding instead of just looking at the top layer (which I suspect is happening currently)?

Update: I have created a plunker showcasing the basic setup of my application: https://plnkr.co/edit/eywuWmPRseUkmVPbTEOf?p=preview

In the provided example, you'll notice that the data model searches by top-level properties effectively but fails to return any results when searching for nested items.

Answer №1

In my understanding of the question, it seems like flattening the data could be beneficial for you:

const flattenObject = function(object) {
    let flattened = {};

    for (let key in object) {
        if (!object.hasOwnProperty(key)) continue;

        if ((typeof object[key]) === 'object') {
            let nestedFlattened = flattenObject(object[key]);
            for (let nestedKey in nestedFlattened) {
                if (!nestedFlattened.hasOwnProperty(nestedKey)) continue;

                flattened[key + '.' + nestedKey] = nestedFlattened[nestedKey];
            }
        } else {
            flattened[key] = object[key];
        }
    }
    return flattened;
};

let newFlattenedData = flattenObject(data);

Original code from: https://gist.github.com/penguinboy/762197

Answer №2

To achieve the desired outcome, follow the instructions below:

1. Declare the following variable in your component:

jsonVal:any=JSON; // for using JSON.stringify and indexOf
  1. Utilize *ngIf to filter values from input using indexOf
    <input type="text" [(ngModel)]="filterString">
    <div *ngFor="let data of result">
      <div *ngIf="jsonVal.stringify(data).indexOf(filterString)!= -1">{{data| json}}</div>
      </div>

For a code example, visit: https://stackblitz.com/edit/angular-ht2afv?file=app/app.component.html

A test object "Campus2" with value "Omaha2" has been included for testing purposes.

Answer №3

When searching for a nested property in your data, consider using the map function or similar methods.

It's recommended by the Angular team to perform filtering in your component rather than using pipes in the template for better performance. You can find more information about this here.

An example implementation could be:

const data = [{//your data}]

let filteredData = [];

data.map(val => {
          if (val.Attribute.filter(name => name.AttributeName === "Foo").length > 0) {
            filteredData.push(val)
          }
        });

This code assumes that your data is stored as an array of objects.

If you're concerned about mutating your original data object, you can create a copy like this:

const data = [{//your original data}]
const dataToFilter = JSON.Parse(JSON.stringify(data))

Creating a deep copy of your data prevents accidental changes to the original object. However, this method may not work well with data objects containing functions.

Upon revisiting your question, it seems my previous solution may not directly address your needs. In that case, flattening your data structure as suggested by Zelda7 or creating a custom filtering method might be more suitable.

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

Concealing content to prevent it from being accessed through HTML and JavaScript inspection techniques

I created a website with a simple guessing game where users can win if they enter the right code. My approach involves using JavaScript: <script> function z() { var b = document.getElementById('idea'); var a = document.g ...

How can you use ES6 pure Javascript to set the src attribute of an html collection of images from an array of paths as values for each image?

Currently, I have an array filled with different src values like [path1, path2, path3], and a corresponding HTML collection which has the same number of elements as the array. I am looking for a way to assign each value from the array to set the src attrib ...

Unable to store user data in the MongoDB Database

I'm currently facing an issue while trying to store user information in my MongoDB database. Everything was working fine until I implemented hashing on the passwords using bcrypt. After implementing password hashing, I am encountering difficulties in ...

Tips for passing multiple values with the same key in Axios as parameters

I need to develop a function that allows users to select multiple categories and subcategories, then send their corresponding ids as a query string using Axios. For example, if a user selects category IDs 1 and 2, along with subcategory IDs 31 and 65, the ...

Sencha Touch - List Creation - How to apply a class to the final item in the list

I am currently working on a list creation process using the following format: var listTpl = new Ext.XTemplate( '<div class="menuListItemContainer">', '<h1>MENU</h1>', '< ...

Tips on generating and receiving shadows in threeJs

As someone who is relatively new to working with threeJS, I have been trying to figure out how to make the shadow of the torus appear on the PlaneGeometry positioned behind it. I experimented with the .castShadow and .receiveShadow properties, but unfortu ...

put a script in the function.php file

I am struggling to figure out how to add my script to my function.php file in Wordpress. Can anyone help me with this? Here is the code I need to add: <script type="text/javascript"> $(function() { $( '#ri-grid' ).gri ...

Is it possible to set the state property in React js using the axios response?

After receiving data from axios, I am trying to store the response in a state value for rendering it in html. However, even though response.results displays the data when printed out, setting response.results in setState() results in an empty value. Here ...

Extract CSS from Chrome developer tools and convert it into a JavaScript object

Recently, we have started incorporating styles into our React components using the makeStyles hook from Material-UI. Instead of traditional CSS, we are now using JavaScript objects to define styles. An example of this is shown below: const useStyles = ma ...

Is there a way to eliminate a tag that includes all attributes except for certain ones?

Here is the code I am working with: var str = `<p>paragraph<a>link</a></p> <div class="myclass"> <div>something</div> <div style="mystyle">something</div> ...

The drag-and-drop feature for uploading files is not functioning properly

After following the JavaScript drag and drop script tutorial mentioned here and using the PHP upload script provided here, I made modifications to the XHR request to upload.php in the JS code. The progress now reaches 100%, but the uploaded image does not ...

Encountering an error: Reading an undefined property - NodeJS, Express, and Mongoose

These are the two functions I have: exports.list = function (req, res){ Material.find(function(err, materials) { res.render('materials/list', {title: 'Pagina Materiali', materials: materials}); }); } exports.modify = function (req ...

Search the table for checked boxes and textboxes that are not empty

Could you suggest alternative ways to express the following scenario? I have a table with 3 rows. Each row contains a column with 3 checkboxes and another column with just a text box. I would like it so that when the values are retrieved from the database ...

Adding routes dynamically in nodeJS using Express is a powerful way to manage your server

Is there a way to dynamically add paths to nodeJS within a running program? Instead of relying on kludged solutions like resetting the server when files change, I am looking for a more efficient method. Any suggestions? EDIT: This project is focused on pr ...

Retrieving the Value of a Member in an Object using Angular

Is there a way to retrieve the value of an object in Angular using a variable as the member identifier? For example: --> my Angular class object: Object1 { name: foo property2: bar } --> my function: myFunction(memberName: string) { return Ob ...

Can I prevent users from selecting Today and future dates in Angular with ngx-bootstrap datepicker?

https://i.sstatic.net/hXpjn.pngHi there, I'm new to Angular and could use some assistance. I tried using the following code snippet to disable today and future dates: <input class="form-control" placeholder="Datepi ...

What is the method for submitting a POST request with a JSON body that consists of only a string, without any key-value pairs included?

There was a developer who, not knowing the correct JSON format for key-value pairs, created a JSON body that looks like this: { "dog" } Instead of { "dog": "dog" } I must send the request from a JavaScript file, and the body needs to be in JSON f ...

Encountering a problem with Angular 2 router functionality

As a beginner in programming with Node.js, Angular2, and Typescript, I decided to explore the Angular forms and Angular router to enhance my application with new pages. Utilizing Material Design Lite (MDL) for material components in my application, I encou ...

Encountering 404 Errors while Attempting to Reach API Endpoint in an Express.js Application Hosted on cPanel

I have a Node.js application running on cPanel, and I'm facing 404 errors when trying to access an API endpoint within my app. Let me provide you with the setup details: Directory Structure: public_html/ server.mjs index.html node_modules ...

How can I refresh a table's data in Angular Material 2 after making edits without having to reload the entire

In my project, I utilized angular material 2 to present a table of data in the form of orders with each row representing an order. To achieve this, I created a new instance of MatTableDataSource called currentTradesData and initialized it within the ngOnIn ...