Refreshing AngularJS bindings and querying from cache after removing the expanded item

Make sure to check out this related question for more information.

When performing a query with an expand operation to retrieve related entities, and subsequently deleting one of these expanded entities, how does the breeze cache get updated?

I'm facing a situation where, even after deleting an expanded item as per the solution suggested in the referenced question, querying from the cache still shows the deleted item unless I force a server call.

Below is the current function I'm using to fetch data from the cache if available or from the server if not. I'm explicitly calling this function after deleting an entity.

function _getByIdExpanded(resource, id, expand, forceRefresh) {
    var self = this;

    // Check if entity exists in cache and is editable
    if (!forceRefresh) {
        var entity = self.em.getEntityByKey(resource, id);
        if (entity && entity.isReadyForEdit) {
            if (entity.entityAspect.entityState.isDeleted()) {
                entity = null;
            }
            return self.$q.when(entity); // Return entity from cache
        }
    }

    // Fetch entity from server
    return eq.from(resource + 's')
        .where('id', '==', id)
        .expand(expand)
        .using(self.em).execute()
        .to$q(succeeded, self._failed);

    function succeeded(data) {
        var result = data.results;
        var entity = result[0];
        if (!entity) {
            logError('Could not find ' + resource + ' with id: ' + id, null);
            return null;
        }
        entity.isReadyForEdit = true;
        return entity; // Return entity fetched from server
    }
}

UPDATE:

Upon further testing, it seems that the issue lies within Angular rather than Breeze.

Here are two relevant functions in my controller:

function deleteEntity(entity) {
    return bsDialog.deleteDialog(entity.name).then(function () {
        datacontext.markDeleted(entity);
        save().then(function () {
            if (entity.entityType === dboardConfigEntity) {
                $location.path('/subscriber/' + subscriberId);
            } else { getDboardConfig(true); }
        });
    });
}

function getDboardConfig(forceRefresh) {
    if ($routeParams.newOrExisting === 'new') {
        subscriberId = $routeParams.id;
        return vm.dboardConfig = datacontext.dboardConfigs.create(subscriberId);
    }
    return datacontext.dboardConfigs.getByIdExpanded($routeParams.id, forceRefresh)
        .then(function (data) {
        vm.dboardConfig = data;
        subscriberId = vm.dboardConfig.subscriberId;
        vm.hideChildren = false;
    });
}

The 'getDboardConfig' function essentially calls the abstract repository function (mentioned earlier):

function getByIdExpanded(id, forceRefresh) {
    var expand = 'Dims';
    return this._getByIdExpanded(entityName, id, expand, forceRefresh);
}

Below are the 'markDeleted' and 'save' functions within my datacontext:

function markDeleted(entity) {
    return entity.entityAspect.setDeleted();
}

function save() {
    return em.saveChanges()
    .to$q(saveSucceeded, saveFailed);

    function saveSucceeded(result) {
        logSuccess('Successfully saved to the server', result, true);
        return result;
    }

    function saveFailed(error) {
        var msg = config.appErrorPrefix + 'Failed to save changes to the server. '
            + breeze.saveErrorMessageService.getErrorMessage(error);
        error.message = msg;
        logError(msg, error);
        throw error;
    }
}

Snippet from my markup:

<table>
    <thead>
        <th>{{dt.name}}</th>
        <th></th>
    </thead>
    <tbody>
        <tr data-ng-repeat="d in vm.dboardConfig.dims | filter:{ dimTypeId: dt.id }">
            <td>{{d.name}}</td>
            <td>
                <a href="" data-ng-click="vm.edit(d)">
                    Edit
                </a>
                <a href="" data-ng-click="vm.delete(d)">
                    Delete
                </a>
            </td>
        </tr>
     </tbody>
</table>

Despite correctly handling promise resolutions, why do the elements in my table fail to update without manual refreshing?


ANOTHER UPDATE:

Following browser debugging, it seems that although I've marked the child entity for deletion and saved it, upon fetching the updated entity, the deleted child entity remains included but in a detached state, signifying successful deletion by Breeze. Upon reviewing Breeze documentation, the question arises - How can I modify my code so that Angular doesn't bind detached entities? I initially understood that Angular wouldn't display detached entities, yet it appears otherwise...

Answer №1

After extensively searching through posts on Stack Overflow, I finally stumbled upon this particular post.

In my case, the issue was caused by Breeze. It seems that all the code I had written was actually fine.

However, the original design of my "expanded" entity Dim was...

public class Dim
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int DboardConfigId { get; set; }
    public int DimTypeId { get; set; }
    public DimType DimType { get; set; }
}

The entity did not have a navigation property back to DboardConfig. Since I didn't need to navigate to any properties of DboardConfig, I thought it was unnecessary. But apparently, not having this navigation property led to the problem described in my question. By adding

public DboardConfig DboardConfig { get; set; }
as a property in the class, the problem vanished.

I'm intrigued to know why Breeze requires this navigation property for deleting expanded items and ensuring they reflect in the binding?

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

When XMLHttprequest is used to send a POST request, it sometimes

Here is the code I'm using to send a request: let ajaxHandler = new XMLHttpRequest(); ajaxHandler.onreadystatechange = function() { if(ajaxHandler.readyState == 4) { console.log(ajaxHandler.responseText); } } ajaxHandler.open("POST", ...

Contrast and analyze two groups of items

In my application, I have a scope named $scope.users that contains information about all the users, such as: [{"id":1,"name":"Peter Boomsma"}, {"id":2,"name":"Jan Jansen"}, {"id":3,"name":"Kees Keesen"}, {"id":4,"name":"Piet Pietersen"}] Additionally, ...

Angular Form Group without a name

Struggling to loop through my formgroups to identify which ones are valid and add the invalid ones to a new array. I can't seem to grab the name value for each formgroup. this.applicationFormArray = new FormGroup({ selectAppFormGroup:th ...

Preventing touchstart default behavior in JavaScript on iOS without disrupting scrolling functionality

Currently experimenting with JavaScript and jQuery within a UIWebView on iOS. I've implemented some javascript event handlers to detect a touch-and-hold action in order to display a message when an image is tapped for a certain duration: $(document) ...

Unsupported server component type: undefined in Next.js version 13 is not recognized by the server

Encountered some unusual behavior in Next.js 13 while attempting a simple action. I have provided a basic example demonstrating the issue. Seeking assistance in understanding why this is occurring. This scenario involves 3 components: page: import {Conta ...

Modification of window size using jQuery animations

Currently, I am working on creating a sidebar that slides in from the left side of the screen. To achieve this effect, I have set the menu element to float left with a width of 40% and a margin-left of -40%. However, when I try to reveal the sidebar by sw ...

Could Object attributes be incorporated into C#?

When working with JavaScript, it's pretty straightforward to create a new object and set its attributes. For example, if I want to set an attribute of an object, I can simply do `objectName.attributeName = whatever`. However, is there a way to achieve ...

Creating an alphanumeric auto-increment ID system with the powerful combination of AngularJS, PHP,

interface I have created an interface using angularjs, PHP, and MySQL. Within this interface, there is a field called "hop reference" which follows the format 7G/0001 where the first part represents a frequency selected from a combo box, and the second pa ...

Data not being retrieved by Meteor.js / MongoDB query for date range

Here is the code snippet I am using to retrieve data from a Mongo Collection: var currentDate = moment().toISOString(); // Returns: 2016-12-10T20:36:04.494Z var futureDate = moment().add(10, "days").toISOString(); // Returns: 2016-12-20T20:36:04.495Z re ...

Getting rid of the empty spaces between the lines of cards in Bootstrap 4

I want to eliminate the vertical space between the cards in my layout. Essentially, I want the cards to maximize the available space. I am open to using a plugin if necessary, but I have not been able to find any relevant information online (maybe I used t ...

Assign a variable to set the property of a class

Could something similar to this scenario be achievable? const dynamicPropName = "x"; class A { static propName = 1 // equivalent to static x = 1 } A[dynamicPropName] // will result in 1 or would it need to be accessed as (typeof A)[dynamicPropN ...

The hidden DIV containing an ASP.NET CheckBox consistently yields a value of false

I have a group of form elements located within a hidden div which looks like this: <div id="jDivUpdateFolder" style="display:none;"> <asp:TextBox ID="txtEditFolderName" runat="server"></asp:TextBox><br /> <asp:TextBox ID ...

Is there a way to automatically adjust the size of an input field after dynamic spans have been

I am looking to replicate the tagging functionality found on StackOverflow when posting a new question. In this case, spans are dynamically added using an input field located next to them. Here is an example: <div> <div id="multiple-span"&g ...

NodeJS rendering method for HTML pages

We are in the process of developing a fully functional social networking website that will resemble popular platforms like Facebook or Instagram. Our plan is to utilize Node.js on the server side and we are currently exploring the best technology for rende ...

The required element was not discovered

Whenever I attempt to execute npm run serve, it reaches 98% completion and then halts, displaying the following error message: An issue occurred while compiling with a total of 1 error: ...

Retrieve the external JSON file using AngularJS

Attempting to retrieve JSON data using Angular JS has been successful with static data. However, encountering issues when trying to fetch data from an external JSON file. Below is the code and corresponding output: index.html <!doctype html> <ht ...

Creating a JavaScript class definition without the need for instantiation

I am looking to create an empty data class in JavaScript that can later be filled with JSON data. In C#, I would typically do something like this: class Person { string name; int age; Person[] children; var whatever; } However, when I try ...

Tips for updating the text shown in an md-select box without affecting the underlying model

Using the Angular material library directive md-select, I have implemented a feature to display country codes to users. When a country is selected, I want to show only the country's dialing code in the select box. For example, if the user selects Ind ...

The completion event was not triggered during the AJAX request

I am having an issue with a function that I have created to make an ajax call. Despite using the .done method, it does not seem to be firing as expected. Upon checking my console for errors, I came across the following message: https://i.sstatic.net/CbYBR ...

Stopping all animations with JQuery animate()

I have a question about stopping multiple animations. Here's some pseudocode to illustrate my situation: CSS #div1 { position: absolute; background-image: url("gfx/cat.jpg"); width: 60px; height: 70px; background-size: 50%; b ...