"Step-by-step guide on associating JSON data with <li> elements using AngularJS

Currently, I am working on creating an application using AngularJS that involves retrieving data from a database and populating a list item with that data.

To achieve this, I have written a WebMethod as shown below:

[WebMethod]
    public static string getname()
    {
        SqlHelper sql = new SqlHelper();

        DataTable dt = sql.ExecuteSelectCommand("select cust_F_name,Cust_L_Name from customer");

        Dictionary<string, object> dict = new Dictionary<string, object>();
        object[] arr = new object[dt.Rows.Count];

        for (int i = 0; i <= dt.Rows.Count - 1; i++)
        {
            arr[i] = dt.Rows[i].ItemArray;
        }
        dict.Add(dt.TableName, arr);
        JavaScriptSerializer json = new JavaScriptSerializer();
        return json.Serialize(dict);


    }

This method returns the data in JSON format.

I am using the following JavaScript code to bind the data:

var DemoApp = angular.module('DemoApp', []);

DemoApp.factory('SimpleFactory', function () {
    var factory = {};
    var customer;
    $.ajax({
        type: "POST",
        url: "Home.aspx/getname",

        data: JSON.stringify({ name: "" }),
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        async: true,
        success: function (data, status) {
            customer = $.parseJSON(data.d);

        },
        failure: function (data) {
            alert(data.d);
        },
        error: function (data) {
            alert(data.d);
        }
    });


    factory.getCustomer = function () {
        return customer;
    };
    return factory;
});

DemoApp.controller('SimpleController', function ($scope, SimpleFactory) {
    $scope.Customer = SimpleFactory.getCustomer();
});

In my view, the HTML code looks like this:

<html xmlns="http://www.w3.org/1999/xhtml" data-ng-app="DemoApp">
<head runat="server">
    <title></title>
</head>
<body data-ng-controller="SimpleController">
    <form id="form1" runat="server">
    <div>
        Name<input type="text" data-ng-model="Name" />{{ Name }}
        <ul>
            <li data-ng-repeat="customer in Customer | filter:Name">{{ customer.cust_F_name }} -
                {{ customer.cust_L_name }}</li>
        </ul>
    </div>
    </form>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.7/angular.min.js"></script>
    <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
    <script src="Script/Home.js" type="text/javascript"></script>
</body>
</html>

However, despite my efforts, it is not functioning as expected. It works fine when I hard code the data in the factory, but when I try to fetch the data using an AJAX call, it fails. I am struggling to understand why this issue is occurring.

Answer №1

What's causing the issue?

  • Attaching a variable to the scope is problematic when its value is dependent on an asynchronous call.
  • When utilizing third-party libraries that alter the scope, it is necessary to explicitly invoke $scope.$apply().

Opt for $http over $.ajax and embrace promises!

DemoApp.factory('SimpleFactory', function ($http) {
  return {
    getCustomer: function(){          
      return $http.post('Home.aspx/getname',{ name: "" });
    })
  }
}

DemoApp.controller('SimpleController', function ($scope, SimpleFactory) {
    SimpleFactory.getCustomer().then(function(customer){
      $scope.Customer = customer;
    },function(error){
      // handle errors
    });
});

If you still prefer using $.ajax

  • Make sure to manually trigger $scope.$apply() after receiving the response.
  • Employ promises or callbacks to bind data to scope variables.

If you intend to retrieve data from the server before loading the view

  • @Misko Hevery provides valuable insights: Delaying AngularJS route change until model loaded to prevent flicker

Although unrelated to your current issue, ensure jQuery is loaded before angular.js

<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.7/angular.min.js"></script> 

Answer №2

Your issue lies with the JavaScript function "SimpleFactory.getCustomer()" returning before the AJAX call is completed.

It is recommended to use $http in Angular instead of jQuery's ajax for several reasons:

  • $http returns a promise, making it consistent with other areas in Angular and allowing for the use of .success and .done methods that align with Angular conventions.
  • $http automatically sets the content type to 'application/json' for POST requests.
  • The success and error callbacks of $http will execute within the Angular context, eliminating the need to manually trigger a digest cycle - if using jQuery, you may need to call $apply.

You can implement this as shown below:

var DemoApp = angular.module('DemoApp', []);

DemoApp.factory('SimpleFactory', ['$http', function ($http) {
    var factory = {};

    factory.getCustomer = function () {
        var promise = $http.post('Home.aspx/getname', {name: ''});
        promise.catch(function(error) {
            alert(error);
        });            

        return promise;
    };

    return factory;
}]);

DemoApp.controller('SimpleController', ['$scope', 'SimpleFactory', function ($scope, SimpleFactory) {
    SimpleFactory.getCustomer().then(function(customer) {
        $scope.Customer = customer;
    });    
}]);

Answer №3

Factories in AngularJS operate as singletons, meaning that the code you've written will trigger the ajax call when the factory is injected into the controller. This explains why you're not seeing the customer data right away, as the server response is processed after the json data is assigned to the scope variable.

A quick (albeit temporary) solution is to encapsulate the customer object:

DemoApp.factory('SimpleFactory', function ($rootScope) {
  // ...
  var customer = {};
  // ...

  $.ajax({ 
    // ...
    success: function(data) {
      $rootScope.$apply(function() {
        customer.data = data;
      });
    }
    // ...
  });
});

// In view

<li data-ng-repeat="customer in Customer.data"> <!-- ... --> </li> 

A more efficient approach would be to utilize either the built-in $http or the $resource angular service. The latter requires using RESTful services (recommended). If you still prefer to use jQuery ajax calls for some reason, you'll need a way to notify Angular when the ajax call is complete: consider exploring the $q promise service.

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

How can I efficiently remove elements from the end of an array in Vue.js?

Is there a way to splice data starting from the back with a higher index? When clicking on the .delete div, how can I make it so the .image-box div deletes starting from the end? I need help implementing this feature in my code. Here is a snippet: < ...

Inserting data into Elasticsearch via the API using a specific path

I've encountered an issue with cURL commands that I'm hoping to resolve. The following cURL command is successfully working: curl -XPOST http://localhost:9200/test/test -d '{"name":"John", "age":31}' -H 'Content-Type: application/ ...

Error: Unable to locate module: Could not find '@/styles/globals.scss'

I'm encountering an error message with my import statement for the SCSS file in my _app.tsx. Can someone help me find a solution? I'm working with Next.js and have already exhausted almost every resource available online to fix this issue. ...

Issues arising when attempting to replicate a fetch object into an undefined object in React.js

I'm facing an issue where I have defined a 'poke' object and when I try to clone an object into it, I only get a promise fulfilled with the object's link , instead of the actual object. Here's the code snippet: let poke = fetch(url ...

Injecting Ajax-loaded content into an HTML modal

Hey there! I'm currently working on a project involving the IMDb API. The idea is that when you click on a film title, a popup should appear with some details about the movie. I've made some progress, but I'm stuck on how to transfer the mov ...

Issue with rendering Backbone subview correctly

Today, I delved into the world of website development using backbone.js. Surprisingly, after a whole morning of trying to crack a puzzling problem, I find myself stuck. Let me focus on the crucial bits of code here. Initially, I have a View named Navigat ...

What are the steps to incorporating an Image in a React Native application?

My Image is not showing up when I try to render it using image uri, and I'm not sure why. Here is the code snippet I'm using in a React Native project. import React from 'react'; import styled from 'styled-components/native'; ...

Best Practices for Handling an Abundance of Data in React or Java

I am facing a challenge with my project setup, where I have the front end in ReactJS and the backend API in Spring Boot. The task at hand is to display a drop down list filled with records retrieved from the API. Here's the scenario: I receive a list ...

AngularJS: Implementing a toggle click function for a list of items within an iframe

Here's the workflow I'm dealing with: I have a collection of items, each having an ng-click event that triggers the display of an iframe below the clicked item. The process works like this: When clicking an item, a hidden div tag beneath it ap ...

Struggling to generate an HTML table using JSON data

Struggling with generating an HTML table from JSON data, I'm inexperienced and having trouble with the logic. The JSON data I have needs to populate a complex dynamic HTML table. The design of the table is intricate, making it challenging for me to i ...

Display the map using the fancybox feature

I have added fancybox to my view. When I try to open it, I want to display a map on it. Below is the div for fancybox: <div id="markers_map" style="display:none"> <div id="map_screen"> <div class="clear"></div> </div&g ...

Exploring ways to retrieve controller dataset within a custom directive

While experimenting with the angular js scope of a custom directive, I attempted to use controller dataset in a custom directive with a different attribute name but faced some challenges. Please take a look at my code and advise me on the correct way to ac ...

Navigate to the adjacent IDs

I have multiple sections with varying content and links (previous and next) to navigate to the next section. Initially, everything functions properly. However, when adding a new section in between existing ones, I am required to update all the ids to ensu ...

Instructions for activating and deactivating a numerical input field with a checkbox

Is there a way to create a pair of a checkbox and number field that are linked together? When the checkbox is clicked, it should disable the associated number field. Javascript File: $(document).ready(function(){ $("input[name=check]").click(function(){ ...

What are the practical applications and distinctions between single-page and multipage apps in AngularJS?

I've been exploring the differences between single page apps and multi page apps, and I believe I have a good grasp on their distinctions. Unlike multi page apps, a single page app begins by loading a single HTML page and does not fully refresh or ove ...

Transforming a TypeScript enum into an array of objects

My enum is defined in this structure: export enum GoalProgressMeasurements { Percentage = 1, Numeric_Target = 2, Completed_Tasks = 3, Average_Milestone_Progress = 4, Not_Measured = 5 } However, I want to transform it into an object ar ...

Successfully resolved: Inability to dynamically adjust button color according to its state

Currently I am working on a feature where a button changes color when it is disabled, but also has a custom color when enabled. Here is the code snippet I am using: Despite setting blue text for the button, it remains blue even after becoming disabled. Ho ...

Testing the JSONObject Unit Always Returns Null

After staring at this code for what feels like an eternity, I still can't pinpoint the issue. JSONObject jsonResponse = new JSONObject(); jsonResponse.put("JSON", "hi"); String myString = jsonResponse.getString("JSON"); assertEquals("hi", myString); ...

What is the best way to convert a BigDecimal to a decimal format within a JSON response when using JAX

While utilizing Tomee 8 as my application server, I am encountering an issue when my REST service returns a BigDecimal. This is the structure of my service: import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs. ...

Exploring Angularjs End-to-End Testing using Angular-UI's Select2 Component

I am facing a challenge with a partial that has a select2 element using Angular UI http://angular-ui.github.io/ The problem is that the element is marked as required, and even though I have managed to set the field through the code provided below, the req ...