Concealing the parent element within the DOM if its children have no content

<div>
  <h1>Birds</h1>
  <ul>
    <li ng-if="bird.type === 'bird'"
        ng-repeat="bird in creatures">{{bird.name}}</li>
  </ul>
</div>

I received data from the server and I need to display it in the list. However, if the list is empty, I want to hide the entire div container. For instance, if bird.type === 'bird' is not present in the array, I want the div to be hidden. I can't use ng-if="bird.type === 'bird'" directly on the div because I need to access the bird object after the ng-repeat. Is there a way to check if the li is empty and then hide the div?

Check out this Plunkr example

AngularJS ng-repeat handle empty list case - Although similar, this is not exactly what I am looking for. I don't want to hide the li if it's empty, but rather hide the parent div that contains the h1 when the li is empty.

Answer №1

If you want to display a list of birds, you can use the following code:

<div ng-if="hasBirds(creatures)">
  <h1>Birds</h1>
  <ul>
    <li ng-if="bird.type === 'bird'"
        ng-repeat="bird in creatures">{{bird.name}}</li>
  </ul>
</div>

To make this work, you need to add the hasBirds function to your controller or directive.

$scope.hasBirds = function(list){
    return list.filter(function(item){return item.type === 'bird'}).length > 0;
}

By using the hasBirds function, you can easily show or hide the heading based on whether there are any birds in the list.

Answer №2

If you're looking for a better approach in the given scenario, my suggestion would be to implement a filter instead of resorting to "ng-if". You can create a custom filter like this:

angular.module('moduleName').filter(birdsFilter);
function birdsFilter(creature) {
    return creature.type == 'bird';
}

This filter can then be utilized to refactor your code as shown below:

<div ng-hide="birds.length">
  <h1>Birds</h1>
  <ul>
    <li ng-repeat="bird in birds = (creatures | filter:birdsFilter)">{{bird.name}}</li>
  </ul>
</div>

Answer №3

In my opinion, there are multiple viable solutions provided here. However, none of them are fully optimized. My suggestion would be to filter the data in your controller or postlink function.

$scope.animals = {
    dogs: $scope.creates.filter(function(a){return a.type == 'dog'}),
    cats: $scope.creates.filter(function(a){return a.type == 'cat'}),
    birds: $scope.creates.filter(function(a){return a.type == 'bird'}),
    fishes: $scope.creates.filter(function(a){return a.type == 'fish'})
};

By doing this, you will only need to process the array of creatures once, in one location. This eliminates the need for the digest cycle to constantly reassess the array for DOM updates. Your markup would then look like this:

<div ng-if="animals.birds.length">
  <h1>Birds</h1>
  <ul>
    <li ng-repeat="bird in animals.birds">{{bird.name}}</li>
  </ul>
</div>

Answer №4

To display only bird-related items from a list, filter the items based on their type and store the filtered items in a designated scope property. You can then use this property to control the visibility of the corresponding elements.

<div ng-show="birds.length">
  <h1>Birds</h1>
  <ul>
    <li ng-repeat="bird in creatures | filter:birdType as birds">{{bird.name}}    </li>
  </ul>
</div>

Next, define the birdType filter function in your controller:

$scope.birdType = function(creature) {
    return creature.type === 'bird';
};

Answer №5

Utilizing the ng-show="cats.length" attribute to hide div elements when the length is zero.

Performing inline filtering based on object properties such as

cat in creatures | filter:{type: 'cat'} as cats
as explained in this Stack Overflow post.

EXAMPLE IN ACTION:

var app = angular.module('App', []);
app.filter(birdsFilter);
function birdsFilter(creature) {
    return creature.type == 'bird';
}
app.controller('Ctrl', function($scope) {
  $scope.creatures = [
      {
        name : 'Cho-cho',
        type : 'bird'
      },
      {
        name : 'Floo-floo',
        type : 'dog'
      },
            {
        name : 'Pou-pou',
        type : 'bird'
      },
      {
        name : 'Oop-flup',
        type : 'bird'
      },
            {
        name : 'Chio-mio',
        type : 'cat'
      },
      {
        name : 'Floo-floo',
        type : 'dog'
      },
            {
        name : 'Loo-Li',
        type : 'dog'
      },
      {
        name : 'Pops-Mops',
        type : 'bird'
      },
            {
        name : 'Boo-Moo',
        type : 'dog'
      },
      {
        name : 'Iop-Pio',
        type : 'dog'
      },
            {
        name : 'Floop-cho',
        type : 'bird'
      }
      
    ]
});
<!DOCTYPE html>
<html ng-app="App">

<head>
  <script data-require="<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="80e1eee7f5ece1f2eaf3c0b1aeb5aeb7">[email protected]</a>" data-semver="1.5.7" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
  <link rel="stylesheet" href="style.css" />
  <script src="script.js"></script>
</head>

<body ng-controller="Ctrl">
  <div ng-show="birds.length">
    <h1>Birds</h1>
    <ul>
      <li ng-repeat="bird in creatures | filter:{type: 'bird'} as birds">{{bird.name}} </li>
    </ul>
  </div>
  <div ng-show="dogs.length">
    <h1>Dogs</h1>
    <ul>
      <li ng-repeat="dog in creatures | filter:{type: 'dog'} as dogs">{{dog.name}} </li>
    </ul>
  </div>
  <div ng-show="cats.length">
    <h1>Cats</h1>
    <ul>
      <li ng-repeat="cat in creatures | filter:{type: 'cat'} as cats">{{cat.name}} </li>
    </ul>
  </div>
  <div ng-show="fishes.length">
    <h1>Fish</h1>
    <ul>
      <li ng-repeat="fish in creatures | filter:{type: 'fish'} as fishes">{{fish.name}} </li>
    </ul>
  </div>

</body>

</html>

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

Using the map function to iterate over an array of objects retrieved from GetStaticProps in NextJS

Currently, I am working on a mdx blog within the NextJS framework. To achieve this, I have implemented a function called getPostDataByCategory(category) in posts.js located under lib. This function is responsible for filtering posts based on categories. ge ...

How to access the api variable in JavaScript

When attempting to retrieve variables from an API object, I encountered the obstacle of them being nested inside another object named "0" in this particular case. Here is a screenshot from the console: enter image description here Below is the JavaScrip ...

What is the best way to save inputted names as properties of an object and assign the corresponding input values as the values of those properties?

I am searching for a way to dynamically build an object where each property corresponds to the name of an input field and the value of that property is the input's value. Here is the HTML structure: <form> <fieldset> ...

How can you apply a class to a different element by hovering over one element?

Is there a way to darken the rest of the page when a user hovers over the menu bar on my website? I've been playing around with jQuery but can't seem to get it right. Any suggestions? I'm looking to add a class '.darken' to #conte ...

How can I save a Flot chart as a PDF file?

After researching various sources such as a flot issue, a chart comparison, and an answer on Stack Overflow, it seems that exporting a flot chart to PDF may not be fully possible. However, I came across another guideline in this answer suggesting the use o ...

I can't find my unit test in the Test Explorer

I'm currently working on configuring a unit test in Typescript using tsUnit. To ensure that everything is set up correctly, I've created a simple test. However, whenever I try to run all tests in Test Explorer, no results are displayed! It appear ...

What is causing all Vuejs requests to fail in production with the error message "javascript enabled"?

My vuejs application interacts with a REST API in Node.js (Express, MongoDB Atlas). Everything runs smoothly when I run the Vue app on localhost while the Node.js app is on the server. However, when I deploy my dist folder to the server, although the app ...

Increasing and decreasing values

I'd like to create two buttons for increasing and decreasing a value. For example, if the variable k is initially set to 4 and I press the decrement button, it should decrease from 4 to 3. This is what I attempted: var k = 1; function qtrFunction ...

perform an action if any division element is void of content

Currently, I have a statement that checks if any of the Divs with the ID #Drop are empty. If one is found to be empty, an alert is shown. However, there seems to be an issue where the statement stops working when any div contains content. What I am trying ...

Is it possible for Vue data to be handled asynchronosly

Have you ever wondered? Is it possible for Vue's data function to be asynchronous? Imagine needing to fetch data from an API using a library like axios, which only offers async methods. How can this data be loaded into Vue's data function? Con ...

The scrolling speed of the mousewheel in Firefox is notably slower compared to that of Google Chrome

Kindly review this sample link: When I test the above example in Chrome and scroll using the mouse wheel, the page moves up by 100px each time. The Y position is displayed as well. However, if I try the same page in Firefox 26.0 and scroll with the mouse ...

What steps should I take to fix the error message "Uncaught TypeError: Class constructor m must be called with 'new'" that occurs while attempting to access a polymer v2.0 application?

Is there a way to resolve this error that occurs when attempting to open a Polymer v2.0 app on Safari in iOS? Uncaught TypeError: Class constructor m cannot be invoked without 'new' from custom-elements-es5-adaptor. The Polymer v2.0 starter k ...

javascript create smooth transitions when navigating between different pages

As a newcomer to JS, I am currently working on creating a website with an introduction animation. My goal is to have this animation displayed on a separate page and once it reaches the end, automatically redirect to the next webpage. <body onload="setT ...

Using React-Router-Config to dynamically set the page title

I am seeking advice on how to dynamically set page titles using the configuration file in conjunction with react-router-config. Should I use props or Helmet for this purpose? routes.js const routes = [ { title: 'Home', path: ...

Dealing with errors in Next.js when using axios in Express

Currently, I am working on implementing the login feature for my application using an asynchronous call to my API. The issue I am facing is that despite express throwing an error, the .then() function is still executing with the error instead of the actual ...

In React (Next.js), the act of replacing a file is performed instead of adding a file

I kindly request a review of my code prior to making any changes. const test = () => { const [files, setFiles] = useState ([]); //I believe I need to modify the following statement. const handleFile = (e) => { const newFiles = [] for (let i= ...

When implementing ng-select together with <option ng-repeat>, an issue arises where ng-select is incorrectly pointing to undefined values

Currently, I am utilizing ng-select to set the default option as the first choice (Past). However, it seems to display the default option as "undefined." <select ng-model="yearSem" ng-show="integrated" ng-change="enrollCtrl.sendYearAndSem()"> ...

Unveiling concealed content with JQuery

Here is a link to my pen: http://codepen.io/anon/pen/IszKj I am looking to achieve the functionality where clicking on either "any status" or "any date" will reveal a hidden div containing a list of options. My main query is about the best approach to ta ...

Issues arise with the functionality of a basic Vue.js script

I've attempted to execute the following code, which is supposedly the simplest example of Vue.js, but it doesn't seem to be working: <div id="app"> {{ message }} </div> <script> var app = new Vue({ el: '#app', d ...

Retrieving all users in Sqlite database with a specific value

I am looking to identify and access each user who has a specific value in their row. Here is an example code snippet of what I want: sql.prepare("SELECT * FROM raid WHERE raid1 > 0 AND NOT id='685337576810610734'").get().forEach(async (user) ...