JSON data rendering in javascript function [duplicate] - javascript

This question already has answers here:
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
Closed 5 years ago.
I am using bootstrap table to build table with json data dynamically, when i plugged function to consume json from web service the table displays empty rows. I compared the data set and i don't see any errors either. Did anyone face this ? what am i missing ?
Script #1
var data;
$.getJSON("http://xxxxxxxx:8073/data-list", function(json){
data = json;
console.log(" data : "+JSON.stringify(data));
});
/*function to load data to first nav tab map*/
$(function () {
$('#table').bootstrapTable({
data: data
});
});
Log
console.log outputs the data as mentioned below, if i compare between hardcoded json vs json from web service it looks identical.
data : [{"index":1,"name":"MATT","company":"APPLE","key":"123333","description":"Node check"},{"index":2,"name":"Steve","company":"Zynga","key":"124333","description":"Game check"}]
Script #2
The same feature works fine if i have variable holding hardcoded json data.
var data =
[
{
"index": 1,
"name": "MATT",
"company": "APPLE",
"key": "123333",
"description": "Node check"
},
{
"index": 2,
"name": "Steve",
"company": "Zynga",
"key": "124333",
"description": "Game check"
}
]
$(function () {
$('#table').bootstrapTable({
data: data
});
});
View
<tr>
<th class="col-md-5 col-xs-5" data-field="name" data-sortable="true">Name</th>
<th class="col-md-4 col-xs-4" data-field="company" data-sortable="true">Work (Authority)</th>
<th class="col-md-3 col-xs-3" data-field="key" data-sortable="true">Magic Key</th>
</tr>

$.getJSON is asynchronous, your second function is probably going to run prior to getJSON completing and setting data. The solution is to initialize your table in the getJSON callback:
var data;
/*function to load data to first nav tab map*/
$(function () {
$.getJSON("http://xxxxxxxx:8073/data-list", function(json){
data = json;
console.log(" data : "+JSON.stringify(data));
$('#table').bootstrapTable({
data: data
});
});
});

in script #1, $.getJson is an asynchronous function.
So, following, you need to stick your table initialisation inside the async callback.
var data;
$.getJSON("http://xxxxxxxx:8073/data-list", function(json){
data = json;
console.log(" data : "+JSON.stringify(data));
$('#table').bootstrapTable({
data: data
});
});

/*function to load data to first nav tab map*/
$(function () {
$.getJSON("http://xxxxxxxx:8073/data-list", function(json){
data = json;
console.log(" data : "+JSON.stringify(data));
}).then(function(data) {
$('#table').bootstrapTable({
data: data
});
})
});
Because the data variable is not populated until the getJSON finishes. The function call is seeing data data as undefined.
http://api.jquery.com/jquery.ajax/

Because $.getJSON is asynchronous you can use the bootstrapTable load method inside your getJSON:
$('#table').bootstrapTable('load', data);
var data =[
{
"index": 1,
"name": "MATT",
"company": "APPLE",
"key": "123333",
"description": "Node check"
},
{
"index": 2,
"name": "Steve",
"company": "Zynga",
"key": "124333",
"description": "Game check"
}
];
$('#table').bootstrapTable({
});
//$.getJSON("http://xxxxxxxx:8073/data-list", function(json){
//data = json;
//console.log(" data : "+JSON.stringify(data));
$('#table').bootstrapTable('load', data);
//});
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.11.1/bootstrap-table.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.11.1/bootstrap-table.min.js"></script>
<table id="table">
<thead>
<tr>
<th class="col-md-5 col-xs-5" data-field="name" data-sortable="true">Name</th>
<th class="col-md-4 col-xs-4" data-field="company" data-sortable="true">Work (Authority)</th>
<th class="col-md-3 col-xs-3" data-field="key" data-sortable="true">Magic Key</th>
</tr>
</thead>
<tbody></tbody>
</table>

Related

Trying to display a table with data from API, array inside JSON Object ANGULAR

I'm working in a project to help a friend, so most of the code in the services and the backend was already there, so I've been struggling with the structure and sometimes I get lost.
Here's my problem
This is the structure of the data on the API:
{
"title": "",
"iconURL": ",
"linkedRightsIDs": [
""
],
"linkedRights": [
{
"id": ,
"creationDate": "",
"sections": [
"women"
],
"defLanguage": "en",
"countryApplied": "united states",
"statesApplied": [
"all"
],
"title": "",
"translations": [
"en"
],
"disable": false,
"content": null
}
]
}
What I'm trying to achieve, is to make a table inside my component using the LinkedRights data. Right now, this structure only have 1 linkedRight (I deleted the data inside for privacy)
Anyways, here's the method regarding the service and model in my component.ts:
onModelLoadedAsync() {
super.onModelLoadedAsync();
if (this.mode == 'create') {
this.model = LocalityInfo;
} else {
if (this.model.iconURL){
this.imageSrc = this.model.iconURL;
}
}
if(this.mode == 'edit'){
const data= Object.entries(this.model.linkedRights); //this is me just testing
console.log(data);
}
}
here's the html of the table I'm trying to display, this is and edit route so there's a query param for the id in this view
<div class="table-responsive">
<table class="table table-hover">
<thead class="thead-dark">
<tr>
<th>Title</th>
<th>Sections</th>
<th>States</th>
<th>Enabled</th>
<th>Creation Date</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of data">
<td>{{item.title}}</td>
<td>{{item.sections}}</td>
<td>{{item.statesApplied}}</td>
<td>{{!item.disabled}}</td>
<td>{{item.creationDate}}</td>
</tr>
</tbody>
</table>
</div>
</div>
What I was trying to do, was to convert the JSON into an array so I could display it since there's an error that shows on the console that said this:
core.js:6456 ERROR Error: Cannot find a differ supporting object '[object Object]' of type'object'. NgFor only supports binding to Iterables such as Arrays.

DataTables won't run render function after AJAX call

I'm using AJAX to get data into my Datatables table. This is something I've done before and it worked fine, but this time I'm running into an issue.
When I run InitializeDatatables JS function, it successfully generates the table and runs the AJAX which reaches the GetDataForTable controller action. However, nothing more happens once the controller action returns. What should happen is the function in "render" section should run but it does not. No error is given either.
As far as I can tell, this setup is very similar to one I had in another project, but I can't find where I'm making a mistake. One difference is that the previous project was on ASP.NET Core 3.0 and this one is on 2.2.
HTML table setup:
<table id="myTable">
<thead>
<tr>
<th>
Important Stuff
</th>
</tr>
</thead>
//Datatables automatically generates the rest of HTML needed
</table>
JS function that runs on page load:
function InitializeDatatables() {
$('#myTable').DataTable({
"lengthChange": false,
"ajax": {
"url": "/Home/GetDataForTable", //controller action runs and returns
"type": "GET",
error: function (error) {
var test = error; //no error is given
}
},
"columns": [
{ "data": null } //"data: null" to access all JSON data in "render" function(data).
],
"columnDefs": [
{
"targets": 0,
"render": function (data) { //function never runs
var test = data;
return '<span>test</span>';
}
},
{"className": "testClass", "targets": 0} //class name is successfully added
]
});
}
Controller action:
[HttpGet]
public JsonResult GetDataForTable()
{
MyModel model = new MyModel();
model.ImportantStuff = _myProcessingService.GetDataFromDB();
return Json(new { data = model });
}

How to filter search input to show correct autocomplete in JQUERY?

I have a search input where my autocomplete shows but for some reason it the results are not being filtered - can anyone tell or show me a way to filter results to show the correct autocomplete prior in my code below.. Below is the json format and the html code updated. Thanks for the help.
Here is my code
$( function() {
var cache = {};
$( "#searchTextField" ).autocomplete({
minLength: 2,
source: function( request, response ) {
var term = request.term;
if ( term in cache ) {
response( cache[ term ] );
return;
}
$.post( "http://localhost:8080/myApp/JobSearchItem.xhtml", request,
function( data, status, xhr ) {
cache[ term ] = data;
response( data );
});
}
});
} );
JobSearchItem Return JSON
[
{
"id": "9000",
"label": "PROGRAMMER TEST 1 (9000) ",
"value": "90000"
},
]
html
<h:body>
<f:view transient="true">
<tp:header/>
<tp:searchForm/>
<div id="results">
</div>
<h:panelGroup id="dTable" class="container">
</h:panelGroup>
</f:view>
<f:view transient="true">
<div class="jobEntity">
<div class="job-container-header">
<h4>#{testBean.jobEntity.toString()}</h4>
<c:if test="#{testBean.jobEntity.validURLConnection}">
<a href="#{testBean.jobEntity.pGradeDescriptionLink}"
class="btn btn-info-One"
target="_blank">[ Test ]</a>
</c:if>
<h4>#{testBean.jobEntity.mu} - #{testBean.jobEntity.muDescription}</h4>
<h4>#{testBean.jobEntity.specialNotes}</h4>
<h4>#{testBean.jobEntity.syRgeMnSepMsg}</h4>
</div>
<c:if test="${testBean.jobEntity.sectionToDisplay eq 'Range'}">
<table class="table">
<tbody>
<tr>
<th></th>
<c:forEach var="stepNumber" begin="1" end="#{testBean.jobEntity.stepSize}">
<th>Step #{stepNumber}</th>
</c:forEach>
</tr>
<c:forEach items="#{testBean.jobEntity.jobRows}" var="jobRow">
<tr>
<th>#{jobRow.rateType}</th>
<c:forEach items="#{jobRow.steps}" var="step">
<td>#{step.amount}</td>
</c:forEach>
</tr>
</c:forEach>
</tbody>
</table>
</c:if>
</div>
When you specify a remote URL as the datasource like this, the remote server is expected to do the filtering based on the search term given to it by the autocomplete, and return the results already filtered.
Autocomplete only carries out the filtering if you provide it with static data. See http://api.jqueryui.com/autocomplete/#option-source for more details.
N.B. If your remote server is unable to do any filtering (e.g. because it just returns a static file) then you'd have to filter the data client-side in your callback before you return it to the autocomplete. But of course this is not very efficient because you keep downloading all the data and then discarding most of it (unless the browser helpfully caches it).
Since you are calling data from a .xhtml file, it is not going to be able to filter the results, unless you can update the server side script to accept and perform activities based on data posted to it.
I would suggest you gather the static data upfront and then filter based on that. This might look something like:
$( function() {
var myData;
$.get( "http://localhost:8080/myApp/JobSearchItem.xhtml", function( data ){
myData = data;
} );
$( "#searchTextField" ).autocomplete( {
minLength: 2,
source: myData
} );
} );
This assumes that your xhtml is providing a Array of data (usually in JSON format). This can be simple:
[
"Item 1",
"Item 2",
"Item 3"
];
Or something more advanced:
[{
"label": "Item 1",
"value": 1
},{
"label": "Item 2",
"value": 2
},{
"label": "Item 3",
"value": 3
}];
If the data you get back is something else: HTML Table, XML, or text, then using a function with Source will help you. If you update your question and provide an example of the data, we could provide a more complete example or guidance.
Update 1
Given the following JSON Data:
[{
"id": "9000",
"pGrade": "0",
"label": "PROGRAMMER TEST 1"
},{
"id": "6000",
"pGrade": "0",
"label": "WEB PROGRAMMER TEST 1"
}];
This does not comply with the standard Autocomplete expected data. If you are able to POST data to JobSearchItem.xhtml, then you can have it filter first and return data. If JobSearchItem.xhtml does not accept POST, then I would perform a GET of all the data up front and then filter it later. I will include an example of both.
POST
If you are posting the data, the server-side script needs to know what data you are sending it in the form of a variable name and value. You did not supply a variable name in your example and you have not supplied the JobSearchItem.xhtml content, so it's really hard to identify how this script works.
For this example, we will use term and our example data will be we. If this was a GET command, it would look like:
JobSearchItem.xhtml?term=we
For Post we will use an Object that is submitted:
{ "term": "we" };
Here are the basics:
$(function(){
var cache = {};
$("#searchTextField").autocomplete( {
minLength: 2,
source: function(request, response){
var t = request.term;
if (t in cache){
response(cache[t]);
return;
}
var results = [];
$.ajax({
url: "http://localhost:8080/myApp/JobSearchItem.xhtml",
data: {
term: t
},
dataType: "json",
method: "POST",
success: function( data, status, xhr ) {
$.each(data, function(k, v){
results.push({
label: v.label,
value: v.label,
id: v.id,
grade: v.pGrade
});
});
cache[t] = results;
});
response(results);
});
}
});
});
So, in this case, if the user enters we, this is sent to the script, which will filter the results and will send back JSON that should look like:
[{
"id": "6000",
"pGrade": "0",
"label": "WEB PROGRAMMER TEST 1"
}];
Since Autocomplete is expecting an object containing label and value can't just be sent direct to response(). Using $.each() we can iterate the results and adjust so that it's formatted for Autocomplete.
GET
If your obSearchItem.xhtml is static and just provides a list of JSON data, using GET might be a good way to collect this data. Consider that you can get all this data up front, and then use it later. This is the most common way to use Autocomplete, but the data still has to be in the right format.
$( function() {
var myData = [];
$.get("http://localhost:8080/myApp/JobSearchItem.xhtml", function(data){
$.each(data, function(k, v){
myData.push({
label: v.label,
value: v.label,
id: v.id,
grade: v.pGrade
});
});
});
$("#searchTextField").autocomplete({
minLength: 2,
source: myData
});
});
One of these should work.

How to fill backbone collection from JSON

Having the following code:
var Tasks = Backbone.Collection.extend({
url: 'http://localhost:5000/tasks'
});
var TaskView = Backbone.View.extend({
el: '.page',
render: function() {
var that = this;
var tasks = new Tasks();
tasks.fetch( {
success: function(tasks) {
var template = _.template($('#task-list-template').html(), {tasks: tasks.models});
that.$el.html(template);
}
})
}
});
var Router = Backbone.Router.extend({
routes: {
'' : 'home' // intentionally blank for the home page
}
});
// Display logic
var taskListView = new TaskView({ });
var router = new Router();
router.on('route:home', function() {
taskListView.render();
});
Backbone.history.start();
The following HTML:
<body>
<div class="container">
<h1>TODO app</h1>
<hr />
<div class="page"></div>
</div>
<script type="text/template" id="task-list-template">
<table class="table striped">
<thead>
<tr>
<th>Task</th>
<th></th>
</tr>
</thead>
<tbody>
<% _.each(tasks.tasks, function(task) { %>
<tr>
<td><%=task.get('task') %></td>
<td></td>
</tr>
<% }); %>
</tbody>
</table>
</script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.2/underscore-min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.2/backbone-min.js"></script>
<script type="text/javascript" src="todoapp.js"></script>
</body>
and the following JSON return from an AJAX request:
{
"tasks": [
{
"id": 6314025183,
"task": "1"
}
]
}
I was wondering how to fill the Collection with the JSON data. I'm unable to fill my HTML table. I suspect my collection to not being filled properly.
How could I validate the content of the collection?
I'm I filling the collection the right way?
This code is based on this video from Thomas Davis available on youtube.
https://www.youtube.com/watch?v=FZSjvWtUxYk
You have two problems. One is code related and one is unfortunately API related.
The API problem can be solved in two ways, but I'll just lay it out first.
When a Collection requests data (from the url property) it expects an array of data. Unfortunately your API is returning an object:
{
"tasks": [
{
"id": 6314025183,
"task": "1"
}
]
}
This is pretty common in a lot of API design, and really speaks to a general misunderstanding of what makes APIs useful.
You'll notice the data you actually want is here in the tasks key of the object:
[
{
"id": 6314025183,
"task": "1"
}
]
It's an array of task objects, each with an id and - what I assume is - a task id.
Great, so you have two options here: you can fix the API so that a request to a collection route like /tasks returns the collection:
[
{
"id": 6314025183,
"task": "1"
}
]
Or, you can use Backbone's parse method to hack around the junk data.
From the documentation for Collection.parse:
Override this if you need to work with a preexisting API, or better namespace your responses.
Here's a quick example:
var Tasks = Backbone.Collection.extend({
'url': 'http://localhost:5000/tasks',
'parse': function( apiResponse ){
return apiResponse.tasks;
}
});
Note the information contained in that parse method that does not have a home. How do I know that the key of the response is tasks?
If I'm a new developer coming into this code, the fact is that I don't. It's tribal knowledge or knowledge I have to go searching for in the API raw response body. The better solution is to namespace the API response to return the collection as requested.
Your second problem is related to your code. In your code you have a Collection and a View and a template, but in your template, you're treating your tasks like a plain ol' javascript object, using underscore to loop over a key.
Instead, tell your collection how to represent it's data.
A collection is a set of related Models.
var Task = Backbone.Model.extend({});
var Tasks = Backbone.Collection.extend({
'url': 'http://localhost:5000/tasks',
'model': Task,
'parse': function( apiResponse ){
return apiResponse.tasks;
}
});
Now, when you hydrate your collection it will automatically create a model representing each set of discrete data.
You can change your view to look like this:
var TaskView = Backbone.View.extend({
'el': '.page',
'template': _.template($('#task-list-template').html()),
'render': function() {
var that = this;
var tasks = new Tasks();
tasks.fetch( {
success: function() {
that.$el.html( that.template( { 'tasks': tasks } ) );
}
})
}
});
Since all Backbone objects extend underscore in some way or another (see the docs for the details), you don't need to manually wrap the passed in collection in underscore. In fact, doing so will almost always create errors. Your template can look like this:
<html>
<body>
<div class="container">
<h1>TODO app</h1>
<hr />
<div class="page"></div>
</div>
<script type="text/template" id="task-list-template">
<table class="table striped">
<thead>
<tr>
<th>Task</th>
<th></th>
</tr>
</thead>
<tbody>
<% tasks.each( function( task ){ %>
<tr>
<td><%= task.get( 'task' ) %></td>
<td></td>
</tr>
<% }); %>
</tbody>
</table>
</script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.2/underscore-min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.2/backbone-min.js"></script>
<script type="text/javascript" src="todoapp.js"></script>
</body>
</html>
The solution posted here is untested, but should allow you to make major debugging leaps even if it does not completely solve the problems

retrieve the data from json folder with angularjs

Hello I try to make a angularjs application so i retrieve a data from a json folder but it's display lik this ["adventure","sci-fi"]
how can I please remove [" "] from this ["adventure","sci-fi"]
this is my json folder
[
{
"title": "Interstellar",
"genre": [
"adventure",
"sci-fi"
],
"watched": false
},
{
"title": "Inception",
"genre": [
"action",
"mystery",
"sci-fi"
],
"watched": true
}
]
and this my service.js
var app = angular.module('appMovies', [] );
app.service('moviesService', function($http,$q){
var deferred =$q.defer();
$http.get('movies.json').then(function (data)
{
deferred.resolve(data);
});
this.getPlayers = function ()
{
return deferred.promise;
}
})
and this my controller
app.controller('appcontrolles', function($scope,moviesService){
var promise = moviesService.getPlayers();
promise.then(function(data)
{
$scope.players =data.data;
console.log($scope.players);
});
})
and this is my index.html
<table class="table table-striped">
<thead>
<tr>
<th>title</th>
<th>genre</th>
<th>watched</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="movie in players | filter : genre |filter: search.genre |filter : watched ">
<td>{{movie.title}}</td>
<td>{{movie.genre}}</td>
<td><input type="checkbox" name="vu", ng-model="movie.watched",value="true"></td>
</tr>
</tbody>
</table>
thanks for your help
Since movie.genre is an array, when you just put {{movie.genre}}, Angular outputs the value as a string representing an array: ["adventure","sci-fi"].
If you want a simple comma-delimited list of values, you could use the .join() function of an array to create a string with a specify delimiter, like ", ", like so:
<td>{{movie.genre.join(", ")}}</td>
Alternatively, if you want more complex DOM around it, then you could ng-repeat over that array:
<td><span ng-repeat="genre in movie.genre">{{genre}}</span></td>
Off Topic:
You don't need to use $q.defer with something that already returns a promise, like $http - you can just return that promise, and so your service could be simplified to:
app.service('moviesService', function($http){
this.getPlayers = function()
{
return $http.get('movies.json');
}
});
$q.defer is used when you are trying to convert a non-promise async function of some third-party service, for example, which uses on-success and on-error handlers.

Categories

Resources