How to convert json string to ko.observableArray([]), array of objects? - json

I have a ViewModel works with knockout framework and ajax. I can save new items to the database with ajax.Save but I have problem when I want to retrieve the saved data. Here are the codes.
Codes in ViewModel:
self.Categories = ko.observableArray([]);
self.Message = ko.observable("");
elf.GetCategories = function () {
$.ajax({
url: "/Admin/Categories",
cache: false,
type: "GET",
datatype: "json",
contenttype: "application/json;utf8"
}).done(function (data) {
self.Categories(ko.mapping.fromJS(data));
}).error(function (err) {
self.Message("Error! " + err.status);
});
}
console.log(JSON.stringify(data)); returns:
{"categories":[{"Id":1,"Name":"Learning","UrlSlug":"0-learning","Description":"learning"},
{"Id":2,"Name":"Topics","UrlSlug":"0-topics","Description":"posts"},
{"Id":3,"Name":"Shares","UrlSlug":"category-shares","Description":"shares"},
{"Id":4,"Name":"Projects","UrlSlug":"category-projects","Description":"project"}]}
Codes in controller is:
[HttpGet]
public ContentResult Categories()
{
var categories = _weblogServices.Categories();
return Content(JsonConvert.SerializeObject(new {categories}), "application/json;utf8");
}
and the problem is the self.Categories = ko.observableArray([]); is always empty without any data. I also tried these items too, but nothing changed:
ko.mapping.fromJS(data, self.Categories);
self.Categories(ko.mapping.fromJS(data));
self.Categories(ko.mapping.fromJSON(data));
ko.mapping.fromJS(data, {}, self.Categories);
I have a simple table in view :
<table id="tblCategory" class="table table-striped table-bordered
table-responsive table-condensed table-hover">
<thead>
<tr>
<th class="text-center">Name</th>
<th class="text-center">Url Slug</th>
<th class="text-center">Description</th>
</tr>
</thead>
<tbody data-bind="foreach: Categories">
<tr>
<td><span data-bind="text: Name"></span></td>
<td><span data-bind="text: UrlSlug"></span></td>
<td><span data-bind="text: Description"></span></td>
<td><button type="button" class="btn glyphicon glyphicon-pencil"
title="Edit" data-bind="click:$data.GetSelected"></button></td>
<td><button type="button" class="btn glyphicon glyphicon-trash"
title="Delete" data-bind="click:$data.DeleteSelectedCategory">/button></td>
</tr>
</tbody>
</table>
So, the question is how can I convert JSON data to observableArray([])?
UPdate: Chrome debugger says: data and Categories are not available.

You don't need to use mapping at all.
In your ajax call .done, you simply have to do this:
self.categories(data.categories);
As an observable array, categories expect an array as parameter. And according to the result of console.log(JSON.stringify(data)) being: {"categories":[{...}, {...}, ...], the array is on the categories property of the received data.
You don't need to use mapping because you simply need to show the objects inside the array, and you don't want to edit their properties. So they can be left as regular JavaScript objects, without observable properties.

Related

How to list values using ng-repeat using AngularJS and JsonResult ASP.NET MVC

I'm trying to render a list from my JsonResult Controller. It's ok, I receive data in my Angular service, but a in trouble to render it in a list using ng-repeat. It´s renders a big empty list.
When the data is not a list, it´s works.
Angular.
Debug
var app = angular.module('FileApp', []);
app.service('ngFileService', function ($http) {
this.getFileByFileCode = function (fileCodigo) {
var response = $http.get("/Files/GetFile?fileCodigo=" + fileCodigo);
return response;
};
});
app.controller('ngFileController', function ($scope, ngFileService) {
$scope.filterFileCode = "";
$scope.getFilteredFile = function () {
var promise = ngFileService.getFileByFileCode($scope.filterFileCode);
promise.then(function (resp) {
$scope.File = resp.data;
$scope.Message = "Call is Completed Successfully";
}, function (err) {
$scope.Message = "Call Failed " + err.status;
});
};
});
HTML
<tr>
<td>Enter Search Value:</td>
<td><input type="text" ng-model="filterFileCode" class="form-
control" ng-change="getFilteredFile()" /></td>
</tr>
<table class="table table-bordered table-condensed table-striped">
<thead>
<tr>
<th>Documentos Gerais File</th>
<th></th>
<th>CTB</th>
<th>COM</th>
<th>Site</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="f in File">
<td>Documentos</td>
<td>{{f.FileCTB}}</td>
<td>{{f.FileCOM}}</td>
<td>{{f.FileSite}}</td>
</tr>
</tbody>
</table>
Erro
I expect to render a list of boolens values.
**DataCriacao: "/Date(-62135596800000)/"
DataFim: "06/07/2018"
DataInicio: "26/06/2018"
DescricaoServico: null
FileCOM: (2) [true, false]
FileCTB: (2) [false, false]
FileCodigo: 190562
FileCodigoId: 0
FileCodigoNv: null
FileMimeType: null
FileSite: (2) [false, false]**
[SOLVED]
I find de solution making the above solution:
<tbody>
<tr>
<td>Documentos</td>
<td>Comandos</td>
<td><span ng-repeat="(key, value) in File.FileCTB track by $index">
{{value}}</span></td>
<td><span ng-repeat="(key, value) in File.FileCOM track by $index">
{{value}}</span></td>
<td><span ng-repeat="(key, value) in File.FileSite track by $index">
{{value}}</span></td>
</tr>
</tbody>
I solved this problem storing in a viewModel object all date below:
DataCriacao: "/Date(-62135596800000)/"
DataFim: "06/07/2018"
DataInicio: "26/06/2018"
DescricaoServico: null
FileCOM: (2) [true, false]
FileCTB: (2) [false, false]
FileCodigo: 190562
FileCodigoId: 0
FileCodigoNv: null
FileMimeType: null
FileSite: (2) [false, false]
So, I can iterate only in the attribute that is collections ou array.

Method 'load' does not work bootstrap-table

I'm trying to load data and popular a table bootstrap-table through an ajax call, but it does not work with the load method. Trying the data method works normally.
the method is not starting, it also does not display that no result was found
Table
<table id="table-anexo" class="table table-striped table-hover display" style="width:100%">
<thead>
<tr>
<th data-field="id"><span>DOCUMENTO</span></th>
<th data-field="tipo"><span>TIPO</span></th>
<th data-field="dt_anexo"><span>DATA ANEXO</span></th>
<!--<th data-field="acao" data-formatter="" data-events="" ><span>AÇÃO</span></th>-->
</tr>
</thead>
</table>
Function AJAX
function get_anexo_ajax(metodo, editando_id) {
var ticket_id = editando_id;
$.ajax({
type: 'POST',
data: {ticket_id : ticket_id},
url: 'ticket/get_anexo_all',
success: (function (data) {
console.log(data.anexo);
//$('#table-anexo').bootstrapTable({ data: data.anexo });
//$('#table-anexo').bootstrapTable('refresh')
$('#table-anexo').bootstrapTable('load', data.anexo);
}),
});
}
Data JSON
{"anexo":[{"id":"1","tipo":"jpg","dt_anexo":"2018-08-01 11:09:28","mensagem_id":"2","ticket_id":"1"}]}
I think data is the invalid format. And Set data-toggle="table" on a normal table. I tested, it run Ok. You can try:
<table id="table-anexo" data-toggle="table" class="table table-striped table-hover display" style="width:100%">
var obj = JSON.parse(data);
$('#table-anexo').bootstrapTable('load', obj.anexo);

Inserting data into database by WEB API in angular JS

I am new into angular JS and web api world. Recently facing difficulty in sending data into database through web api and angular. I am able to load json data from webapi.Any help will be highly appreciated.
My html:
<div class="container-fluid" ng-controller="SubmitDataCtrl">
<div class="container text-center" style="margin-bottom:5px">
<div id="divTables">
<table id="tbl_SMDetails" class="display responsive nowrap aleft" cellspacing="0" width="100%">
<thead>
<tr>
<th class="all">Name</th>
<th class="all">CTSID</th>
<th class="all">FDID</th>
<th class="all">Name of the Project</th>
<th class="all">Effort Hour</th>
<th class="all">Month</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="showData in loadData">
<td>{{showData.EmpName}}</td>
<td>{{showData.EmpCognizantID}}</td>
<td>{{showData.FDID}}</td>
<td><input id="Text1" type="text" />{{showData.projectName}}</td>
<td><input id="Text1" type="text" />{{showData.effortHour}}</td>
<!--<td>{{date | date:'MM-dd-yyyy}}</td>-->
<td>{{showData.date}}</td>
</tr>
</tbody>
</table>
</div>
</div>
<div>
<a ng-href='#SubmitData' class="btn btn-default" ng-click='go()'>Submit</a><span></span>
<a ng-href='#SubmitData' class="btn btn-default" ng-click=''>Reset</a>
</div>
</div>
My service page looks like:
var request = $http({
method: method_args,
url: myConfig.ServiceURL + url,
data: JSON.stringify(input_data),
Accept: 'application/json',
headers: {'Content-Type':'application/json'},
xhrFields: {
withCredentials: true
}
});
}
and my controller is
App.controller("SubmitDataCtrl", function($scope, ajaxService) {
//login user
ajaxService.MakeServiceCall("employee/GetTeamMember? superVisiorCogniID=256826", "GET", "")
.then(function effortData(data)
{
// alert(data);
$scope.date = new Date();
$scope.loadData = data;
showData = $scope.loadData;
for (var i = 0; i < showData.length; i++)
{
//alert(showData[i].EmpName + showData[i].EmpCognizantID + showData[i].FDID);
}});
$scope.go = function()
{
//alert('clicked');
ajaxService.MakeServiceCall("effort/SaveTeamEfforts?hourLoadDate=08/20/2015&hourLoadByCogniID=256826&forMonth=July", "POST", Employee).then(function save() {
var Employee =
{
"EmpCogniID": showData[i].EmpCognizantID,
"FDTimeCardHour": showData[i].effortHour,
"HourLoadDate": 08/11/2015,
"HourLoad`enter code here`By": "256826",`enter code here`
"ForMonth": "july"
}
}).success(function (Employee)
{
$scope.showData[i] = Employee;
});
alert(Employee); }});
It's hard to answer without knowing what the API POST call should do.
Can you confirm that the POST you are making to effort/saveTeamEfforts works by executing it using a REST tester in the browser?
if that is working, you should add an .error function to your API call and see what error is returned as dan has sugested above
L

Retrieving values from a table cell <td> to a controller

I'm trying to get a specific value from a table cell and pass is to a controller. But it doesn't seem to be working. I show you some of my codes:
This is in the controller:
def searchUser = {
String abc = request.getParameter("harrow")
println(abc)
}
This is in the html page:
<form>
<div style="height: 250px; overflow: scroll; width: 100%;">
<table id="normal">
<g:each in = "${result}">
<tr id="btn">
<td width=10% >${it.ID}</td>
<td width=25% id="harrow">${it.username}</td>
</tr>
</g:each>
</table>
</div>
<input type ="submit" name ="abc" id="opener">
</form>
EDIT
AJAX:
$("#edittable").on('click', function() {
$.ajax({
url: URL,
data: $(this).serialize(),
type: "POST",
success: function(html){
//do something with the `html` returned from the server here
$("#edit1").html(html).dialog("open")
},
error: function(jqXHR, textStatus, errorThrown){
alert('error: ' + textStatus + ': ' + errorThrown);
}
});
return false;//suppress natural form selection
});
I can get the value to pass to the controller, but right now it only retrieves the first row of values rather than the other. Is there something wrong with my AJAX codes? Thank you guys so much.
So to show details of the row, one of the approaches can be:
CONTROLLER METHODS
def rows = [
[id:1, name:'name1'],
[id:2, name:'name2'],
[id:3, name:'name3']
]
def show(){
[results:rows]
}
def showLine(Long id){
render rows.find {it.id == id }
}
VIEW
<html>
<head>
<g:javascript library="jquery" />
<r:layoutResources />
</head>
<body>
<table>
<thead>
<tr>
<th>Action</th>
<th>Id</th>
<th>Name</th>
</tr>
</thead>
<tbody>
<g:each in="${results}" status="i" var="r">
<tr>
<td><g:remoteLink value="Details" id="${r.id}" action="showLine" update="lineDetails">Details</g:remoteLink></td>
<td>${r.id}</td>
<td>${r.name}</td>
</tr>
</g:each>
</tbody>
</table>
<div id="lineDetails">
</div>
</body>
</html>
Basically you call showLine method using AJAX and passing row object id. Then you search for the object and render it back. Rendered data is put into div under the table. It's up to you if you use onclick, button or link in the table. It's also up to you how to show details on results page - use jquery dialog, or something else. Hope it helps

Knockoutjs' foreach not working when single data has returned

I have a table which is shown below. When multiple data comes, it is shown properly but if a single data come, data isn't shown in the table. I suspect absence of brackets in single data..
Multiple Data Sample:
[{"Id":1,"Name":"Tomato soup","Category":"Groceries","Price":1.39},{"Id":2,"Name":"Yo-yo","Category":"Toys","Price":3.75},{"Id":3,"Name":"Hammer","Category":"Hardware","Price":16.99}]
Single Data sample
{"Id":1,"Name":"Tomato soup","Category":"Groceries","Price":1.39}
Table and scripts:
<script type="text/javascript">
$(document).ready(function () {
function ProductViewModel() {
var self = this;
self.productData = ko.observable();
self.productId = ko.observable();
self.getAllProducts = function () {
$.get('/api/products', {}, self.productData);
};
self.getProductById = function () {
$.get('/api/products/' + self.productId(), {}, self.productData);
};
}
ko.applyBindings(new ProductViewModel());
});
</script>
<input id="txtId" type="text" data-bind="value: productId" />
<button id="btnGetSpeProduct" data-bind="click: getProductById">Get Product By Id</button>
<button id="btnGetProducts" data-bind="click: getAllProducts">Get All Products</button><br />
<table data-bind="with: productData">
<thead>
<tr>
<th>
Name
</th>
<th>
Category
</th>
<th>
Price
</th>
</tr>
</thead>
<tbody data-bind="foreach: $data">
<tr>
<td data-bind="text: Name">
</td>
<td data-bind="text: Category">
</td>
<td data-bind="text: Price">
</td>
</tr>
</tbody>
</table>
The foreach binding can accept either an array or an object specifying various options. In this case, Knockout thinks the object you're giving it is the latter. It will work if you use the object syntax and specify your data using the data option.
<tbody data-bind="foreach: {data: $data}">
Sample: http://jsfiddle.net/mbest/Dta48/
Yes - it has everything to do with the "absence of brackets in single data".
The one with brackets means that it's an array; a list which can can iterate (foreach).
The one without brackets means that it's an object; something which can be stored inside an array, but can not be iterated using foreach.
So, you want it to act like an array so you can iterate over the result. First step, you'll need to use an observableArray instead of observable:
self.productData = ko.observableArray();
Next, you'll need to push the data you $.get to that array, instead of directly binding them.
$.get('/api/products', function(data) {
// Iterate over the data variable, and use
// self.productData.push(ITEM)
// to add it to the array
});
That should do it - good luck!
use observableArray instead of observable
self.productData = ko.observableArray();