Widget Issue

vidhya_mouli
Giga Sage

I am trying to create a custom widget that will display the records based on condition. Have limited the number of records to 5 and when the user clicks on load more button, next 5 records should be displayed. However, this is not working. Can someone help me to fix my script?

HTML:

 

<div ng-controller="OutageWidgetController">
  <label for="stateFilter">Select State:</label>
  <select ng-model="selectedState" id="stateFilter">
    <option value="all">All</option>
    <option value="solved">Solved</option>
    <option value="work_in_progress">Work in Progress</option>
  </select>

  <button ng-click="fetchRecords()">Fetch Records</button>

  <div ng-repeat="record in limitedRecords">
    <div class="record-container" style="padding: 15px; border: 1px solid #ccc; margin-bottom: 10px;">
      <div>
        <div class="message-container">
          {{record.message}}
        </div>
        <div class="published-container">
          {{record.sys_created_on}}
        </div>
      </div>
      <div class="description-container">
        {{record.short_description}}
      </div>
    </div>
  </div>

  <button ng-show="showLoadMoreButton" ng-click="loadMoreRecords()">Vis flere</button>
</div>

 

 

Client Side Script:

 

function ($scope, $http) {
  $scope.limitedRecords = [];
  $scope.showLoadMoreButton = false;
  $scope.totalRecords = 0;

  $scope.fetchRecords = function () {
    var state = $scope.selectedState;
		

    // Adjust API request based on the selected state
    var queryParams = state === 'all' ? {} : { sysparm_query: 'u_state=' + state };

    // Make an AJAX request to the server to fetch records
    $http.get('/api/now/table/cmdb_ci_outage', { params: queryParams })
      .then(function (response) {
        $scope.totalRecords = response.data.result.length;
        $scope.showLoadMoreButton = $scope.totalRecords > 5;

        // Display only the first 5 records initially
        $scope.limitedRecords = response.data.result.slice(0, 5);
      });
  };

$scope.loadMoreRecords = function () {
  // Display additional 5 records each time the "Load More" button is clicked
  var nextBatch = $scope.limitedRecords.length + 5;
  $scope.limitedRecords = $scope.limitedRecords.concat($scope.fetchRecords($scope.selectedState).slice(nextBatch - $scope.limitedRecords.length));
  $scope.showLoadMoreButton = nextBatch < $scope.totalRecords;
};

}

 

Server Side Script:

 

(function () {
  data.fetchRecords = function (state) {
    var gr = new GlideRecord('cmdb_ci_outage');
    gr.addQuery('u_state', state);
    gr.query();
    
    var records = [];
    while (gr.next()) {
      var record = {
        short_description: gr.short_description.toString(),
        message: gr.message.toString(),
        sys_created_on: gr.sys_created_on.toString()
      };
      records.push(record);
    }
    return records;
  };
})();

 

1 ACCEPTED SOLUTION

Sohithanjan G
Kilo Sage
Kilo Sage

Hi @vidhya_mouli,

It seems like there are a few issues in your code that need to be addressed. Let's go through them:

  1. Client Side Script: In the loadMoreRecords function, you're trying to call the fetchRecords function again to fetch the next batch of records. However, this function doesn't return the records directly; instead, it makes an asynchronous HTTP request and updates the $scope.limitedRecords variable once the response is received. So, you can't directly use it to fetch more records synchronously like that.

  2. Client Side Script: To fix this, you need to modify the loadMoreRecords function to keep track of the starting index of the next batch of records and update the limitedRecords array accordingly when the response is received.

  3. HTML: Ensure that the loadMoreRecords function is called when the "Load More" button is clicked.

     

    Client Side:

 

function ($scope, $http) {
  $scope.limitedRecords = [];
  $scope.showLoadMoreButton = false;
  $scope.totalRecords = 0;
  $scope.startIndex = 0;
  $scope.batchSize = 5;

  $scope.fetchRecords = function () {
    var state = $scope.selectedState;

    // Adjust API request based on the selected state
    var queryParams = state === 'all' ? {} : { sysparm_query: 'u_state=' + state };

    // Make an AJAX request to the server to fetch records
    $http.get('/api/now/table/cmdb_ci_outage', { params: queryParams })
      .then(function (response) {
        $scope.totalRecords = response.data.result.length;
        $scope.showLoadMoreButton = $scope.totalRecords > $scope.batchSize;

        // Display only the first batch of records initially
        $scope.limitedRecords = response.data.result.slice(0, $scope.batchSize);
      });
  };

  $scope.loadMoreRecords = function () {
    // Update the starting index for the next batch of records
    $scope.startIndex += $scope.batchSize;

    // Adjust API request based on the selected state
    var queryParams = $scope.selectedState === 'all' ? {} : { sysparm_query: 'u_state=' + $scope.selectedState };

    // Make an AJAX request to the server to fetch the next batch of records
    $http.get('/api/now/table/cmdb_ci_outage', {
      params: Object.assign({}, queryParams, {
        sysparm_limit: $scope.batchSize,
        sysparm_offset: $scope.startIndex
      })
    }).then(function (response) {
      // Concatenate the new batch of records with the existing ones
      $scope.limitedRecords = $scope.limitedRecords.concat(response.data.result);

      // Update the "Load More" button visibility
      $scope.showLoadMoreButton = $scope.limitedRecords.length < $scope.totalRecords;
    });
  };
}

 


HTML:

 

<div ng-controller="OutageWidgetController">
  <label for="stateFilter">Select State:</label>
  <select ng-model="selectedState" id="stateFilter">
    <option value="all">All</option>
    <option value="solved">Solved</option>
    <option value="work_in_progress">Work in Progress</option>
  </select>

  <button ng-click="fetchRecords()">Fetch Records</button>

  <div ng-repeat="record in limitedRecords">
    <div class="record-container" style="padding: 15px; border: 1px solid #ccc; margin-bottom: 10px;">
      <div>
        <div class="message-container">
          {{record.message}}
        </div>
        <div class="published-container">
          {{record.sys_created_on}}
        </div>
      </div>
      <div class="description-container">
        {{record.short_description}}
      </div>
    </div>
  </div>

  <button ng-show="showLoadMoreButton" ng-click="loadMoreRecords()">Load More</button>
</div>

 

 

HIT Helpful & Accept Solution !!

Please mark as Accepted Solution if this solves your query and HIT Helpful if you find my answer helped you. This will help other community mates too..:)

View solution in original post

2 REPLIES 2

Sohithanjan G
Kilo Sage
Kilo Sage

Hi @vidhya_mouli,

It seems like there are a few issues in your code that need to be addressed. Let's go through them:

  1. Client Side Script: In the loadMoreRecords function, you're trying to call the fetchRecords function again to fetch the next batch of records. However, this function doesn't return the records directly; instead, it makes an asynchronous HTTP request and updates the $scope.limitedRecords variable once the response is received. So, you can't directly use it to fetch more records synchronously like that.

  2. Client Side Script: To fix this, you need to modify the loadMoreRecords function to keep track of the starting index of the next batch of records and update the limitedRecords array accordingly when the response is received.

  3. HTML: Ensure that the loadMoreRecords function is called when the "Load More" button is clicked.

     

    Client Side:

 

function ($scope, $http) {
  $scope.limitedRecords = [];
  $scope.showLoadMoreButton = false;
  $scope.totalRecords = 0;
  $scope.startIndex = 0;
  $scope.batchSize = 5;

  $scope.fetchRecords = function () {
    var state = $scope.selectedState;

    // Adjust API request based on the selected state
    var queryParams = state === 'all' ? {} : { sysparm_query: 'u_state=' + state };

    // Make an AJAX request to the server to fetch records
    $http.get('/api/now/table/cmdb_ci_outage', { params: queryParams })
      .then(function (response) {
        $scope.totalRecords = response.data.result.length;
        $scope.showLoadMoreButton = $scope.totalRecords > $scope.batchSize;

        // Display only the first batch of records initially
        $scope.limitedRecords = response.data.result.slice(0, $scope.batchSize);
      });
  };

  $scope.loadMoreRecords = function () {
    // Update the starting index for the next batch of records
    $scope.startIndex += $scope.batchSize;

    // Adjust API request based on the selected state
    var queryParams = $scope.selectedState === 'all' ? {} : { sysparm_query: 'u_state=' + $scope.selectedState };

    // Make an AJAX request to the server to fetch the next batch of records
    $http.get('/api/now/table/cmdb_ci_outage', {
      params: Object.assign({}, queryParams, {
        sysparm_limit: $scope.batchSize,
        sysparm_offset: $scope.startIndex
      })
    }).then(function (response) {
      // Concatenate the new batch of records with the existing ones
      $scope.limitedRecords = $scope.limitedRecords.concat(response.data.result);

      // Update the "Load More" button visibility
      $scope.showLoadMoreButton = $scope.limitedRecords.length < $scope.totalRecords;
    });
  };
}

 


HTML:

 

<div ng-controller="OutageWidgetController">
  <label for="stateFilter">Select State:</label>
  <select ng-model="selectedState" id="stateFilter">
    <option value="all">All</option>
    <option value="solved">Solved</option>
    <option value="work_in_progress">Work in Progress</option>
  </select>

  <button ng-click="fetchRecords()">Fetch Records</button>

  <div ng-repeat="record in limitedRecords">
    <div class="record-container" style="padding: 15px; border: 1px solid #ccc; margin-bottom: 10px;">
      <div>
        <div class="message-container">
          {{record.message}}
        </div>
        <div class="published-container">
          {{record.sys_created_on}}
        </div>
      </div>
      <div class="description-container">
        {{record.short_description}}
      </div>
    </div>
  </div>

  <button ng-show="showLoadMoreButton" ng-click="loadMoreRecords()">Load More</button>
</div>

 

 

HIT Helpful & Accept Solution !!

Please mark as Accepted Solution if this solves your query and HIT Helpful if you find my answer helped you. This will help other community mates too..:)

Thank you very much. It worked.