I am trying to create a real-time filter on a table using knockoutjs.
I have managed to get everything to work when I statically create the observable array like this:
$(function() {
var assets = [
{id: "1", poster: "Pic010.jpg", name: "Asset1", category: "category1", type: "Movie", popup: "1" },
{id: "2", poster: "Pic06.jpg", name: "Asset2", category: "category2", type: "Movie", popup: "2" },
{id: "3", poster: "Pic04.jpg", name: "Asset3", category: "category1", type: "Pop-up", popup: "3" },
{id: "4", poster: "Pic07.jpg", name: "Asset4", category: "category2", type: "Pop-up", popup: "4" },
{id: "5", poster: "Pic011.jpg", name: "Asset1", category: "category3", type: "Promo", popup: "5" }
];
var viewModel = {
assets: ko.observableArray(assets),
query: ko.observable(''),
search: function(value) {
viewModel.assets.removeAll();
for(var x in assets) {
if(assets[x].name.toLowerCase().indexOf(value.toLowerCase()) >= 0) {
viewModel.assets.push(assets[x]);
}
}
}
};
viewModel.query.subscribe(viewModel.search);
ko.applyBindings(viewModel);
});
JSFiddle of working code: http://jsfiddle.net/7ZLdk/1/
Now when I try to load the observable array data via ajax like this:
var assets = [];
$.ajax({
url: '/Assets/getJson/',
type: "GET",
dataType: 'json',
success: function (data) {
console.log(data);
viewModel.assets(data);
}
});
the data is displayed correctly in the table when the page is loaded, but when I start typing in the search input, all the data disappears.
I would appreciate it if someone could explain what I am doing incorrectly in the AJAX load? TIA
You are better off creating a ViewModel function, so the viewmodel only accesses data within itself:
$(function() {
$.ajax({
url: '/Assets/getJson/',
type: "GET",
dataType: 'json',
contentType: "application/json",
success: function (data) {
console.log(data);
var viewModel = new ViewModel(data);
ko.applyBindings(viewModel);
}
});
});
function ViewModel(assets) {
var self = this;
self.assets = ko.observableArray(assets);
self.allAssets = assets;
self.query = ko.observable('');
self.search = function(value) {
self.assets.removeAll();
for(var x in self.allAssets) {
if(self.allAssets[x].name.toLowerCase().indexOf(value.toLowerCase()) >= 0) {
self.assets.push(self.allAssets[x]);
}
}
};
self.query.subscribe(self.search);
}
I have resolved the problem.
I was not populating the assets array. This is the updated ajax call:
$.ajax({
url: '/Assets/getJson/',
type: "GET",
dataType: 'json',
contentType: "application/json",
success: function (data) {
console.log(data);
viewModel.assets(data);
assets = data; // THIS WAS MISSING
}
});
Related
First I want to create a simple array with data from input
And I want to do a loop and create an array with the line from the table.
some code here.
var first_array = {
"warehouse": $("#warehouse").val(),
"pricelist": $("#pricelist").val(),
"date": $("#date").val(),
"docstatus": "DR",
"paymentterm": $("#paymentterm").val()
}
var second_array = []; //Thanks to sagar1025 help create the second array
$("#table_main tbody > tr").each(function() {
var celdas = $(this).find('td');
second_array.push({
"line": $(celdas[0]).html(),
"code": $(celdas[1]).html()
});
});
/*Here my ajax*/
$.ajax({
data: {
array1: first_array,
array2: second_array
},
url: "<?php echo base_url() ?>main/save_data",
type: 'POST',
async: false,
cache: false,
success: function(response) {
},
error: function() {
toastr.error('ERROR', '', {
progressBar: true,
closeButton: true
});
}
});
Now I need to loop the second array in my php file
Here is how I declare one var from the first_array
$docstatus = trim($this->input->post('array1[docstatus]', TRUE));
$array = $this->input->post('array2[]', TRUE);
Im using codeigniter
This is how you push or add multiple objects to an array
var second_array = [];
$("#table_main tbody > tr").each(function() {
var celdas = $(this).find('td');
second_array.push({
"line": $(celdas[0]).html(),
"code": $(celdas[1]).html()
});
});
The Ajax call should be like something like this:
$.ajax({
data: {
array1: first_array,
array2: second_array
},
url: "<?php echo base_url() ?>main/save_data",
type: 'POST',
async: false,
cache: false,
success: function(response) {
},
error: function() {
toastr.error('ERROR', '', {
progressBar: true,
closeButton: true
});
}
});
I think you are confusing between arrays and object, arrays are denoted with [] example var array=[1,2,3,4] objects are denoted with {} ex: var Obj={color:"red"}
you could send an object in your ajax call that contains both arrays or both objects depending on what you want so for instance you could do something like:
var globobj={}
var first_object= {
"warehouse": $("#warehouse").val(),
"pricelist": $("#pricelist").val(),
"date": $("#date").val(),
"docstatus": "DR",
"paymentterm": $("#paymentterm").val()
}
var second_object= {
"line": $(celdas[0]).html(),
"code": $(celdas[1]).html()
}
globobj.first_object=first_object
globobj.second_object=second_object
so now that your objects are both combined you could use the globobjto make you ajax call
i have a form on select from dropdown the request goes to the controller and returns the following in
JSON formate
[{id: 2, slug: "manager", name: "Assistant Manager", created_at: "2019-12-10 09:20:45",…}]
0: {id: 2, slug: "manager", name: "Assistant Manager", created_at: "2019-12-10 09:20:45",…}
created_at: "2019-12-10 09:20:45"
id: 2
name: "Assistant Manager"
permissions: [{id: 2, slug: "edit-users", name: "Edit Users", created_at: "2019-12-10 09:21:01",…}]
0: {id: 2, slug: "edit-users", name: "Edit Users", created_at: "2019-12-10 09:21:01",…}
slug: "manager"
updated_at: "2019-12-10 09:20:45"
now i want to iterate from permissions and show name in another drop-down with multiple selection buit i don't know how to iterate from this JSON i tried the following script but doesn't work
$(document).ready(function () {
$("#roles").on('change', function () {
var query = $(this).val();
// alert(query);
if (query != '') {
$.ajax({
url: "{{route('get-roles-ajax-call')}}",
method: "POST",
dataType: 'JSON',
data: {"_token": "{{ csrf_token() }}", query: query},
success: function (data) {
var values = $.parseJSON(data)
$(values).each(function(i,val){
$.each(val,function(key,val)
{
console.log(key + " : " + val);
});
});
}
});
}
return false;
});
});
When setting this line dataType: 'JSON' you are already telling the $.ajax function to return JSON.
Quoted from jQuery documentation of $.ajax
"json": Evaluates the response as JSON and returns a JavaScript object.
So there is no need to parse the data once you've received it. Is is already JSON.
Now loop through every object in the data to search for the permissions property. If the object has the permissions property and the value of that is an array that is not empty then loop over each object in the permissions array and look for the the name property on each permission.
$.each(data, function(i, entry) {
var permissions = entry.hasOwnProperty('permissions');
if (permissions && permissions.length) {
$.each(entry.permissions, function(j, permission) {
console.log(permission.name);
});
}
});
Though I would suggest that you modify the, or create a new, server response so that all this filter work is done server side and you only have to call the server to get the data you need.
In order to load some data from the server after the page has loaded I have the following script:
<script>
export default {
data() {
return {
imageDirectory: "../../images/",
fileName: "img",
extension: ".png",
products:
[
{
name: 'loading data',
imageUrl: require("../../assets/t1.png")
}
]
}
},
name: "ProductList",
created: function () {
this.fetchData();
},
methods: {
fetchData: function () {
$.ajax({
type: "GET",
timeout: 1200000,
url: 'api/test',
contentType: "application/json",
dataType: "text",
success: function (data) {
window.alert(data);
this.products = [{
name: 'success' + 'test',
imageUrl: require("../../assets/t1.png")
}] },
error: function (data) {
this.products = [{
name: 'failed' + 'test',
imageUrl: require("../../assets/t1.png")
}]
}
});
}
}
}
</script>
Now when I run this I do get the alert window showing me that it did indeed fetch the data, however, it does not actually manage to update the object in question (product name remains loading data and not success test). If I move the code
this.products = [{
name: 'success' + 'test',
imageUrl: require("../../assets/t1.png")
}]
into the created: function() like so:
created: function () {
this.products = [{
name: 'success' + 'test',
imageUrl: require("../../assets/t1.png")
}]
this.fetchData();
}
it does actually update the data. So this means that both the code to fetch the data is accurate and the placeholder to update the data is functional, so why is the data not getting updated?
(note that the code to update the data is a placeholder).
in your fetchData function you have used 'this' keyword inside $.ajax() which can confuse compiler to which object you are referring so why not try this:
fetchData: function () {
let app = this;
$.ajax({
type: "GET",
timeout: 1200000,
url: 'api/test',
contentType: "application/json",
dataType: "text",
success: function (data) {
window.alert(data);
app.products = [{
name: 'success' + 'test',
imageUrl: require("../../assets/t1.png")
}] },
error: function (data) {
app.products = [{
name: 'failed' + 'test',
imageUrl: require("../../assets/t1.png")
}]
}
});
}
The list is being filtered properly but the label is showing as undefined. When I select the item, the value is binded.
Below is my code along with the screenshots:
$(document).on('ready',function(){
$('#search').autocomplete({
source: function(req,res) {
$.ajax({
url: "/search",
dataType: "json",
type: "GET",
data: {
term: req.term
},
success: function(data) {
res($.map(data, function(item) {
return {
label: item.name,
value: item.id
};
}));
},
error: function(xhr) {
alert(xhr.status + ' : ' + xhr.statusText);
}
});
},
select: function(event, ui) {
}
});
});
Before Selection
After selection
I tried debugging the label and value using alert function. The values are perfect. I'm unable to figure out the error.
item.name
item.id
Here is the callback response:
[
{
"id":"1",
"name":"Android"
},
{
"id":"2",
"name":"Akira"
},
{
"id":"3",
"name":"Andy"
},
....
]
You are returning different property names in ajax success function.
Can you try to use these property names instead.
[
{
"label":"1",
"value":"Android"
},
....
]
$.ajax({
url: "url",
type: 'POST',
data: {
},
success: function (res) {
//console.log(res);
var obj = JSON.parse(res);
$('#od').html('<option value=""> Select</option>');
for (var i = 0, len = obj.length; i < len; i++){
$('#id').append('<option value='+ obj[i].item_id +'> '+ obj[i].item_name +'</option>');
}
}
});
here is my code for get all option you can try this
I am using KendoUI Web and have set up a TreeView with two levels of hierarchy which are loading data from a CRUD service using the transport option of the DataSource:
var Level2 = kendo.data.Node.define({
id: "Level2_Id",
hasChildren: false,
fields: {
"Level2_Id": { type: "number" },
"Name": { type: "string" },
"Level1_Id": { type: "number" }
}
});
var level2DataSource = {
transport: {
read: {
url: "/service/level2",
type: "get",
dataType: "json"
},
create: {
url: "/service/level2",
type: "post",
dataType: "json"
}
},
schema: {
model: Level2
}
};
var Level1 = kendo.data.Node.define({
id: "Level1_Id",
hasChildren: true,
fields: {
"Level1_Id": { type: "number" },
"Name": { type: "string" },
},
children: level2DataSource,
});
var level1DataSource = new kendo.data.HierarchicalDataSource({
transport: {
read: {
url: "/service/level1",
type: "get",
dataType: "json"
},
create: {
url: "/service/level1",
type: "post",
dataType: "json"
}
},
schema: {
model: Level1
}
});
var myTreeview = $("#treeview").kendoTreeView({
dataSource: leaguesDataSource,
template: kendo.template($("#treeview-template").html())
});
Reading the data works fine on both levels.
Creating new items is done by calling .append() on the TreeView and then .sync() on the level 1 DataSource.
This results in a POST request to my service which returns the new JSON object. The tree view updates just fine.
However, when doing the same thing on level 2, the treeview will remove all items and only show level 2 children of the level 1 item that the new item was appended to.
The GET requests return a JSON array of level 1 or level 2 items like
result of /service/level1
[
{Level1_Id:1,Name:"Item 1"},
{Level1_Id:2,Name:"Item 2"},
{Level1_Id:3,Name:"Item 3"},
]
result of /service/level2
[
{Level2_Id:1,Name:"Item 2.1",Level1_Id:2},
{Level2_Id:2,Name:"Item 2.2",Level1_Id:2}
]
The POST requests return a single object of the same format.
What format do I need to return in my service so the treeview will update correctly on level 2 after appending an item?
Expected result:
- Item 1
- Item 2 (append here)
- Item 2.1
- Item 2.2 (new item)
- Item 3
Actual result after POST request:
- Item 2.1
- Item 2.2 (new item)
your syntax it not right. your must write
schema:{model:{id: "IdLevel", children: "items", hasChildren: "hasChildren"}}
with hierarchical data.
For example you must have your data like this :
[
{ categoryName: "SciFi", items: [
{ movieName: "Inception", rating: 8.8 },
{ movieName: "The Matrix", rating: 8.7 }
] },
{ categoryName: "Drama", hasAssignedMovies: true }]