items within an unordered list that can be collapsed

Answer:

Nikhil was on the right track with his solution, but I had to make some modifications. Specifically, I needed to create and initialize an empty array to display the details properly. Here's the updated code:

if (this.name.toLowerCase() == value.name.toLowerCase()) {
    this.showingDetails.push(false);
    return value;
}
else {
    return null;
}

After making these changes, I followed Nikhil's instructions for the rest of the process.

Query:

I have a website with an unordered list containing name, link, and a lengthy text block for each item. The data is dynamically fetched from a database, making it difficult to determine the number of items in advance. Is there a way to hide the long text initially and show it only when the user clicks a specific link? Currently, toggling visibility displays the text for all items simultaneously.

I'm using Angular/typescript for development, and here's what I have implemented so far:

<ul class='list-group' *ngFor='#item of Items'>
    <li>
        <hr>
        <p><strong>{{ item.sourceType }}:</strong> <em>{{ item.sourceName }}</em></p>
        <p><strong>Link:</strong> <a target="_blank" href="{{ item.source }}">{{ item.source }}</a></p>
        <p><strong>Details:</strong> <a (click)="showDetails()">{{ showHideTxt }}</a></p>   
        <p style="white-space:pre-wrap" *ngIf="showingDetails">{{ item.details }}</p>
    </li>
</ul>

And in the component class:

items:Item[] = [];
name:string = "unknown";
foundItems:Item[];
showHideTxt:string = "show";
showingDetails:boolean = false;
itemSubscription:Subscription;

constructor(private itemService:ItemService) 
{
}   

ngOnInit()
{
    this.itemSubscription = this.itemService.getItems()
        .subscribe(
            itemData => this.items = itemData.json(),
            err => console.log(err),
            () =>   this.foundItems = this.items.filter((value)=>{
                        return value.searchName.indexOf(this.name.toLowerCase()) != -1 ? value : null
                    });
        )
    this.name = decodeURI(this.routeParams.get('name'));

    console.log(this.name.toLowerCase());
}

ngOnDestroy()
{
    this.itemSubscription.unsubscribe();
}

showDetails()
{
    this.showingDetails = !this.showingDetails
    this.showingDetails
        ?this.showHideTxt = "hide"
        :this.showHideTxt = "show";
}

Answer №1

To set up the visibility state of each list item in your component class, create a boolean array named showingDetails. You can remove the showHideTxt property as it is not necessary.

In your HTML file, pass the index of the list item to the showDetails() method, and within that method, toggle the visibility of the item at that particular index.

Here is how your final code should appear:

Component class:

showingDetails = new Array(this.items.length).fill(false);

showDetails(index) {
    this.showingDetails[index] = !this.showingDetails[index];
}

HTML:

<ul class='list-group' *ngFor='let item of items; let i=index'>
    <li>
        <hr>
        <p><strong>{{ item.sourceType }}:</strong> <em>{{ item.sourceName }}</em></p>
        <p><strong>Link:</strong> <a target="_blank" href="{{ item.source }}">{{ item.source }}</a></p>
        <p><strong>Details:</strong> <a (click)="showDetails(i)">{{ showingDetails[i] === true ? 'Hide' : 'Show' }}</a></p>   
        <p style="white-space:pre-wrap" *ngIf="showingDetails[i]">{{ song.details }}</p>
    </li>
</ul>

EDIT:

Due to the asynchronous nature of HTTP calls, any code referencing the items array outside the subscription block will execute before the code inside the block. This leads to the items array being undefined.

A solution would be to move the affected code inside the subscription block as shown below:

/* Other code */
...
...
showingDetails: boolean[];


ngOnInit()
{
    this.itemSubscription = this.itemService.getItems()
        .subscribe(
            itemData => this.items = itemData.json(),
            err => console.log(err),
            () =>   {
              this.foundItems = this.items.filter((value)=> {
                 return value.searchName.indexOf(this.name.toLowerCase()) != -1 ? value : null
                    });

               // initializing 'showingDetails' property inside this block
               this.showingDetails = new Array(this.foundItems.length).fill(false);
            }
        )
    this.name = decodeURI(this.routeParams.get('name'));

    console.log(this.name.toLowerCase());
}

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

Why is this strange red dot character 🔴 appearing in the URL in FireFox?

While browsing the web, I came across a website with a strange red blob in the URL. It's something I've never seen before. What could possibly be the reason for this unique feature?! Note that you have to visit the page to see it for yourself. T ...

Activate the popup for sharing or bookmarking by clicking on a regular link

I am currently utilizing a Share/Bookmark script: <div class="singles-right"> <a href="#" class="bookmark"></a> <script type="text/javascript" src="http://static.addinto.com/ai/ai2_bkmk.js"></script> <a href="#" clas ...

changing web pages into PDF format

I need to convert HTML to PDF on a Linux system and integrate this functionality into a web application. Can you suggest any tools that are capable of doing this? Are there any other tools I should consider for this task? So far, I have attempted the foll ...

Retrieve the HTML tags following the modification of my information in ASP.NET

Apologies for any language errors, I am new to asp.net development. 1- I have a table with dynamically created rows and columns based on user selection of row and column numbers. 2- Each row in the table has the following controls: A- One textbox, one l ...

What is the proper way to implement a class decorator in TypeScript?

How can a class decorator be implemented to accept only specific classes? A attempted solution is as follows: class Component { age: number; } function registerComponent(name: string) { return <T extends Component>(constructor: T): T => { ...

Css3 techniques for creating seamless cloud animations

I am struggling with a CSS3 animation effect. For example, the clouds in this animation continue to animate for 7 seconds, then return to the starting point and begin animating again. However, when they come back to the starting point, it appears as if the ...

Determine if a user's inputted number matches a randomly generated number using Javascript

I am trying to generate a random number, prompt the user to input a number, compare the two, and display a popup indicating whether they match or not. Below is the code that I have written for this functionality. function generateRandomNumber() { ...

Tips for positioning two spans next to each other at full width using CSS

In my custom file manager, I am looking to display truncated filenames in a unique way. It is crucial to show the beginning and ending of the filename, so simply using overflow:ellipsis is not sufficient. The tiles displaying the filenames can adjust thei ...

The mysterious appearance of the <v-*> custom element in Vuetify Jest

Currently, I am in the process of writing unit tests for my project using Jest. The project itself is built on Vue, Vuetify (1.5), TypeScript, and vue-property-decorator. One particular area of focus for me has been creating a basic wrapper for the <v- ...

What is the correct way to include an NPM package in a Plunker project?

Encountered an error while utilizing angular2-infinite-scroll. Attempting to replicate it in a plunkr. Experimented with using npmcdn, hence added this line in the index.html file: <script src="https://npmcdn.com/<a href="/cdn-cgi/l/email-protectio ...

Testing the local transmission of form data via Javascript: A Step-by-Step guide

Currently studying how to send forms using JavaScript by manually creating an XMLHttpRequest. Towards the end of the provided example, there's a note: Note: If you want to send data to a third party website, keep in mind that this use of XMLHttpRequ ...

What may be causing the MuiThemeProvider to override the style of a component?

Within my outer component, I am utilizing MuiThemeProvider: <MuiThemeProvider theme={full_theme_e}> <div> <AppBar /> <Filter /> </div> </MuiThemeProvider> Inside the Filter component, I have specified a ...

Adding a component to a page in Angular 4: A step-by-step guide

Currently engaged in a project that involves creating a mobile application design within a web application. I'm wondering how to display my Component object on a page using ViewChild? I have a list of PageComponents, below is the PageComponent class ...

I am experiencing difficulties with integrating the Stripe checkout API into my MEAN stack development

view error image here I encountered this issue in the developer tools. check terminal error image here This is the error shown in the backend terminal. explore Stripe documentation for guidance Here are the helpful Stripe docs that guided me through. ...

Retrieving template variable within a directive's host listener function

Can 'habitCellInfo' be accessed from the template within the onvalueChanged host listener? <div *dxTemplate="let habitCellInfo of 'habitEditCellTemplate'"> <dx-select-box (onValueChanged)=" onHabitEdi ...

Start a new typescript project from scratch

Seeking assistance in setting up a blank TypeScript project with a package.json, TypeScript and HTML file. I am looking for something akin to the Stackblitz blank-typescript project. If anyone could provide me with a step-by-step guide on how to create su ...

Fade in a CSS class using jQuery

I'm attempting to incorporate a basic fadeIn() CSS effect on specific objects that are tagged with the "button" class. My goal is to have the "hoverbutton" class fade in when the object is hovered over, and then fade out when the cursor moves away fro ...

Creating a versatile function that can function with or without promises is a valuable skill to have

I am currently working on developing a versatile sort function that can function with or without promises seamlessly. The intended structure of the function should look something like this: function sort<T>(list: T[], fn: (item: T) => string | nu ...

Tips for aligning numbers in a monospaced ordered list

Is there a way to align the numbers in a numbered list within a table using monospace font so that they are at the same level as bullets on a bullet list? Simplest example: ol { font-family: monospace; } ul, ol { margin-top: 10px; margin-bottom: ...

How can we incorporate interactive icons into the navigation bars on our Weebly site?

Recently, while using Weebly to design a website, I stumbled upon a webpage () that explains how to add icons to the navigation bar. Below is the code provided: /* External Fonts */ @font-face { font-family: 'dashicons'; src: url('fonts/ ...