Issue with knockout view - unable to remove item from view after deletion

I'm facing an issue with my code that deletes an exam from a list of exams on a page, but the deleted exam still shows up until the page is manually refreshed. This pattern works correctly on other pages, so I don't understand why it's not working on this specific page.

 // Used to handle the click event for Delete
    remove = (exam: Models.Exam) => {
        $("#loadingScreen").css("display", "block");
        var examService = new Services.ExamService();

        examService.remove(exam.examId()).then(() => {
            examService.getByFid().then((examinations: Array<Models.Exam>) => {


                this.exams(examinations);

                this.template("mainTemplate");
            });
        }).fail((error: any) => {
                // Add this error to errors
                this.errors([error]);
                window.scrollTo(0, 0);
            }).fin(() => {
                $("#loadingScreen").css("display", "none");
            });
    }

This is the UI code responsible for displaying the list of exams:

    <div class="section module">
        <!-- ko if: exams().length > 0 -->
        <!-- ko foreach: exams.sort(function(a,b){return a.mostRecentDateTaken() > b.mostRecentDateTaken() ? 1:-1}) -->
        <div class="addremove_section bubbled">
            <a class="button open_review" data-bind="click: $root.edit">Edit</a>
            <a class="button open_review" data-bind="click: $root.remove">Delete</a>
            <div class="titleblock">
                <h4 data-bind="text: 'Exam Name: ' + examTypeLookup().examTypeName()"></h4>
                <div data-bind="if:examEntityLookup()!=null">
                    <div data-bind=" text: 'Reporting Entity: ' + examEntityLookup().description()"></div>
                </div>
                <div data-bind="text: 'Most recent date taken: ' +  $root.formatDate(mostRecentDateTaken())"></div>
                <div data-bind="text: 'Number of attempts: ' + numberOfAttempts()"></div>
                <div data-bind="text: 'Pass/Fail Status: ' + $root.PassFailEnum(passFailId())"></div>
            </div>
            <div class="clearfix"></div>
        </div>
        <!-- /ko -->
        <!-- /ko -->
        <!-- ko if: exams().length == 0 -->
        <div class="addremove_section bubbled">
            <div class="titleblock">
                <div>No Exams Have Been Entered.</div>
            </div>
        </div>
        <!-- /ko -->
    </div>

EDIT: After some investigation, I found that removing the sort function in the view solves the issue:

<!-- ko foreach: exams.sort(function(a,b){return a.mostRecentDateTaken() > b.mostRecentDateTaken() ? 1:-1}) -->

Changing it to:

<!-- ko foreach: exams -->

This workaround works, but I need the data to be sorted. Any suggestions?

Answer ā„–1

Instead of sorting in the view, I decided to move the sorting logic to the service. It seems like there may be an issue with sorting in Knockout.js that's causing this unexpected behavior.

<!-- ko foreach: exams -->


        [HttpGet]
        [Route("api/exam")]
        public IEnumerable<TDto> GetApplicantExams()
        {

                var dtos = GetCollection(() => _examService.GetApplicantExams(UserContext.Fid).OrderBy(e => e.DateTaken));
                return dtos.ForEach(t => AddItems(t));

        }

Answer ā„–2

This issue does not stem from a flaw in Knockout. When the sorting function is invoked without being controlled by a computed or dependent observable, there is no mechanism to prompt it to re-sort. Essentially, the link between the UI (or more technically, the bindingHandler) and the ko.observable that KO uses to monitor changes has been severed.

I have encountered this problem numerous times in my professional experience, and typically, I follow a common approach:

var viewModel = {
    list: ko.observableArray(),
    removeFromList: removeFromList,
    addToList: addToList
}

// In your HTML, use foreach: sortedList instead of just list
viewModel.sortedList = ko.computed(function(){
    // As this computation is within the change tracking system, sorting will happen as expected
    return viewModel.list().sort(customSortFunction);
});

// Since you cannot modify a standard computed property, perform operations on the original array like so

function removeFromList(item){
    viewModel.list.remove(item); // Modifying the array triggers the sorted computed update and consequently updates the UI
}
function addToList(item){
    viewModel.list.push(item);
}

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

Is it possible to synchronize functions in node.js with postgresql?

Iā€™m facing some challenges in managing asynchronous functions. Here is the code snippet that's causing the issue: var query = client.query("select * from usuario"); query.on('row', function(user) { var queryInterest = client. ...

Exploring the functionalities of Express and Socket.io

I am new to creating a Node.js app using express V 3.4.8 and socket.io V 0.9.16 to display a map with markers showing where users are connecting to the site. I am doing this to learn more about node.js and how to incorporate maps into my projects. However, ...

Tips for validating and retrieving data from a radio button paired with an input box in reactjs

I'm diving into the world of React and facing a challenge with multiple radio buttons that have associated input fields, like in this image: https://i.stack.imgur.com/Upy3T.png Here's what I need: If a user checks a radio button with a ...

Tips for ensuring elements within a modal receive immediate focus when opened in Angular 2

I am relatively new to Angular JS and I am encountering some challenges with implementing a directive in Angular 2 that can manage focusing on the modal when it is opened by clicking a button. There have been similar queries in the past, with solutions pr ...

When transferring the code to the src folder, tRPC encounters issues and stops functioning

Currently, I am working on developing a basic Twitter clone using Next and TRPC. While tRPC is up and running smoothly, I am looking to streamline my code by consolidating it all within the src directory. However, upon moving everything, I encountered an i ...

What is the best way to combine two sections in html/css/bootstrap?

I've been trying to create a simple webpage with a navigation bar and a section below it, but I keep running into an issue where there's unwanted white space between the nav bar and the next section in blue. Is there a way to eliminate this gap a ...

Translating coordinates into their corresponding location on the chart

I'm currently working with a dataset containing information about an area in Western Europe. I am trying to convert coordinates into values within this table, facing a challenge similar to the one described in this query. However, I lack experience in ...

Transfer the document into JavaScript by copying and pasting

I am in need of some assistance with a basic form that includes an input field. While the form is functional, I would like to provide users with the option to upload a file by simply pasting it into the browser using CTRL+V. Is there a way to achieve this ...

Display HTML content generated by JavaScript in the page source

Can the HTML elements I've added through JavaScript and jQuery codes be displayed in the page source (ctrl+U)? ...

Most effective method for converting a table of data to TypeScript

Searching for an effective method to map a table of enum (or interface) data to the correct location. For instance, Smoke Sensor - Push Button can only be linked to SS - PI SYMBOL and Smoke Sensor - PushButton can only be associated with 000 - TTT PARAMET ...

Tips for utilizing JavaScript functions within Vue directives?

Let's say I have a JS function that looks like this: function myFunc() { return true; } Now, I want to display an element if the output of the function is true: <p v-if="myFun()">I am Test</p> I understand that I can place the myFun ...

What is the best way to implement rate limiting or throttling on a Strapi API?

Our company relies on a simple strapi API implemented in node.js and hosted on Heroku. Despite our efforts, we have not been able to find a solution to implement rate limiting, as it appears that Heroku does not offer throttling add-ons and strapi lacks bu ...

Navigating the complexities of transferring data between components

I recently started working with Angular 6 and encountered an issue while trying to share data in my project. Below is the code snippets: 1) Component Sidebar: selectedCategory(type:any) { this.loginService.categoryType = type; // need to pass this d ...

Showing JSON information on a web browser

Here is a snippet of JSON data that I am working with: {"earthquakes":[{"datetime":"2011-03-11 04:46:23","depth":24.39999999999999857891452847979962825775146484375,"lng":142.36899999999999977262632455676794 ...

Creating unique appbars for different sections on my sidebar in ReactJs

I am trying to implement a responsive drawer and AppBar using material-ui (@material-ui/core). My goal is to display a specific AppBar for each section of the drawer. For instance, when the user navigates to the Timetable section, I want the AppBar label t ...

My component fails to load using Angular Router even though the URL is correct

I have been experiencing an issue while trying to load my Angular component using the router. The component never appears on the screen and there are no error messages displayed. app-routing-module { path: '', redirectTo: '/home', ...

Improprove the Express Router in a Node.js application

Is there a way to avoid repeating the isUserAuth and isAdminAuth middleware on each endpoint? Can I apply them just once so they work for all routes without having to specify them individually? const { createBranch, getAllBranch, getBranch } = require(&apo ...

How to Retrieve a Variable from the Parent Component in a Child Component using Angular (1.5) JS

I am currently working on abstracting the concept of a ticket list building into an angular application using 2 components. 1st component --> ("Smart Component") utilizes $http to fetch data and populate an array called populatedList within the parent ...

Error: Unable to change image -- TypeError: Cannot assign value to null property 'src'

As I work my way through the textbook for one of my classes, I am practicing by building an image swapping page. The concept is simple - clicking on a thumbnail swaps out the main image and enlarges it as if it were linking to another web page. Despite fol ...

Is it possible that the background color won't change on the second click?

Initially, my first click worked fine and successfully changed the background color. However, as soon as I added a second condition, it stopped working. var showBox = $('.show'); showBox.click(function(){ if (parseInt($(this).attr('v ...