displaying jstree data from ajax is missing text - javascript

I'm trying to load an entire tree using the 'alternate method', i.e. I don't specify children, but instead specify parents. Here's my data being sent:
[{"id":"0","parent":"#","text":"Chart of Accounts"},
{"id":"1","parent":"0","text":"Assets"},
{"id":"5","parent":"1","text":"Bank Accounts"},
{"id":"14","parent":"5","text":"Cash Box"},
{"id":"16","parent":"14","text":"Wallet"},
{"id":"15","parent":"5","text":"Personal Acct"},
{"id":"2","parent":"0","text":"Liabilities"}]
I have jquery code that gets executed and which loads the data (i can see it in Fiddler):
<div id="jstree_div"></div>
<script>
$(function() {
$('#jstree_div').jstree({
core: {
data: {
url: '/api/GetEntireTree',
datatype: 'json',
plugins: [ "wholerow", "ui", "themes" ],
data: function(node) {
return { id: node.id };
}
}
}
});
});
</script>
However, when I set a breakpoint at function(node), node shows in the debugger as:
node
children: []
children_d: []
id: "#"
parent: null
parents: []
state: {loaded: false, failed: false, loading: true }
[[Prototype]]: Object
After the breakpoint the result is it shows the first line (Chart of Accounts), but no children. I have not found a good example of loading data via ajax using the 'alternate method'.
Here is a jsfiddle showing the problem: https://jsfiddle.net/vzqtocnh/1/

Related

Select2 - Pass back additional data via ajax call

Ok, I feel like I'm going crazy here. I'm using the select2 jquery plugin (version 4), and retrieving data via ajax. So you can type in a name, and it will return that contact information. But I also want to return what organization that contact is a part of.
Here is my select2 initialization:
$('#contact_id').select2({
ajax: {
url: 'example.com/contacts/select',
dataType: 'json',
delay: 250,
data: function (params) {
return {
q: params.term,
page: params.page
};
},
processResults: function (data) {
return {
results: data
};
},
cache: true
},
minimumInputLength: 3,
maximumSelectionLength: 1
});
And here is the data I'm returning (laravel framework):
foreach($contacts as $con) {
$results[] = [
'id' => $con->contact_id,
'text' => $con->full_name,
'org' => [
'org_id' => $con->organization_id,
'org_name' => $con->org_name
]
];
}
return response()->json($results);
So isn't 'org' supposed to be attached to either the created option or select element by select2? So I could do something like $('#contact_id').select2().find(':selected').data('data').org or $('#contact_id').select2().data('data').org or something like that?
Idealistically, this would look like:
<select>
<option value="43" data-org="{org_id:377, org_name:'Galactic Empire'}">Darth Vader</option>
</select>
I swear I confirmed this worked last week, but now it's completely ignoring that org property. I have confirmed that the json data being returned does include org with the proper org_id and org_name. I haven't been able to dig anything up online, only this snippet of documentation:
The id and text properties are required on each object, and these are the properties that Select2 uses for the internal data objects. Any additional paramters passed in with data objects will be included on the data objects that Select2 exposes.
So can anyone help me with this? I've already wasted a couple hours on this.
EDIT: Since I haven't gotten any responses, my current plan is to use the processResults callback to spawn hidden input fields or JSON blocks that I will reference later in my code. I feel like this is a hacky solution given the situation, but if there's no other way, that's what I'll do. I'd rather that than do another ajax call to get the organization. When I get around to implementing it, I'll post my solution.
Can't comment for now (low reputation).. so... answering to slick:
Including additional data (v4.0):
processResults: function (data) {
data = data.map(function (item) {
return {
id: item.id_field,
text: item.text_field,
otherfield: item.otherfield
};
});
return { results: data };
}
Reading the data:
var data=$('#contact_id').select2('data')[0];
console.log(data.otherfield);
Can't remember what I was doing wrong, but with processResults(data), data contains the full response. In my implementation below, I access this info when an item is selected:
$('#select2-box').select2({
placeholder: 'Search Existing Contacts',
ajax: {
url: '/contacts/typeahead',
dataType: 'json',
delay: 250,
data: function(params){
return {
q: params.term,
type: '',
suggestions: 1
};
},
processResults: function(data, params){
//Send the data back
return {
results: data
};
}
},
minimumInputLength: 2
}).on('select2:select', function(event) {
// This is how I got ahold of the data
var contact = event.params.data;
// contact.suggestions ...
// contact.organization_id ...
});
// Data I was returning
[
{
"id":36167, // ID USED IN SELECT2
"avatar":null,
"organization_id":28037,
"text":"John Cena - WWE", // TEXT SHOWN IN SELECT2
"suggestions":[
{
"id":28037,
"text":"WWE",
"avatar":null
},
{
"id":21509,
"text":"Kurt Angle",
"avatar":null
},
{
"id":126,
"text":"Mark Calaway",
"avatar":null
},
{
"id":129,
"text":"Ricky Steamboat",
"avatar":null
},
{
"id":131,
"text":"Brock Lesnar",
"avatar":null
}
]
}
]

Kendo TreeView with remote datasource only populates the root elements

I am having difficulty in fully populating a Kendo TreeView with a remote datasource, although with a local datasource it works fine.
In short, the first sample below uses a local datasource. This all works perfectly:
// local datasource, works perfectly
var local = new kendo.data.HierarchicalDataSource({
data: [
{
"DeviceGroupId": 1,
"DeviceGroupName": "Superdeluxe Devices",
"Devices": [
{
"Id": 1000,
"Name": "My First Device"
},
{
"Id": 1001,
"Name": "My Second Device"
}
]
}
],
schema: {
model: {
children: "Devices"
}
}
});
// initialize - this works!
$("#list-of-devices").kendoTreeView({
dataSource: local,
dataTextField: ["DeviceGroupName", "Name"],
loadOnDemand: false
});
Again, the sample above works just fine. Now, the second sample below does not: it only populates the treeview's root element ("Superdeluxe Devices"). And it totally ignores the children.
// remote datasource
var remote = new kendo.data.HierarchicalDataSource({
transport: {
read: {
url: "/api/devices/list", // <-- confirmed this works
dataType: "json",
contentType: "application/json"
},
schema: {
model: {
children: "Devices"
}
}
}
});
// initialize
$("#list-of-devices").kendoTreeView({
dataSource: remote, // the issue: only shows top level nodes
dataTextField: ["DeviceGroupName", "Name"],
loadOnDemand: false
});
So, the issue in the second sample is that only the top level nodes are shown, without any option to expand.
I have looked into the following:
The data in both datasources, local and remote, are identical (I copied the results from remote into local)
Enabled/disabling the loadOnDemand option, now setting it by default to 'false'
Mapping stuff through the schema.data and schema.parse functions to no effect
Looked into the both the HierarchicalDataSource API and the TreeView API, as well as the Binding to remote data demo
Looked into older UserVoice issue, which indicates that it's possible now to fully load and render a TreeView
Summarized, I can't seem to figure out why the local variant works perfectly - and the remote does not show the children. Any suggestions?
The problem is in your remote DataSource definition where you defined the schema.model as part of the transport and it is not. It should be:
var remote = new kendo.data.HierarchicalDataSource({
transport: {
read: {
url: "list.json",
dataType: "json",
contentType: "application/json"
}
},
schema: {
model: {
children: "Devices"
}
}
});
schema is at the same level than transport.

How to display nested data items in FuelUX tree bootstrap plugin

I'm trying to implement the FuelUX tree plugin and I've followed the example so far but I need a nested structure. I'm assuming the tree plugin is capable of handling nested children? is this correct?
var treeDataSource = new TreeDataSource({
data: [
{ name: 'Test Folder 1', type: 'folder', additionalParameters: { id: 'F1' },
data: [
{ name: 'Test Sub Folder 1', type: 'folder', additionalParameters: { id: 'FF1' } },
{ name: 'Test Sub Folder 2', type: 'folder', additionalParameters: { id: 'FF2' } },
{ name: 'Test Item 2 in Folder 1', type: 'item', additionalParameters: { id: 'FI2' } }
]
},
{ name: 'Test Folder 2', type: 'folder', additionalParameters: { id: 'F2' } },
{ name: 'Test Item 1', type: 'item', additionalParameters: { id: 'I1' } },
{ name: 'Test Item 2', type: 'item', additionalParameters: { id: 'I2' } }
],
delay: 400
});
So far it seems to load the top level items into the opened folders rather than the nested data items. This is what the demo on their site also does but this doesn't seem as if its the desired interaction. Can anyone confirm if this is expected behaviour?
Can anyone point me to code where they've created a nested data tree using this plugin? Is there something really obvious I am missing?
I am actually in the process of writing a blog post on this very issue.
The solution I have developed is not for the faint-of-heart. The problem is that the folder objects do not support instantiation with child data. Also, adding children is no trivial task. I spun up a quick fiddle that you can pick through to get an idea of how to accomplish your goal. I am using this same solution only that my addChildren function calls out to an MVC route via AJAX and gets back a JSON object to populate the children dynamically.
You can literally, copy and paste the code from my fiddle and start using the addChildren function out-of-the-box.
I'm sorry for the lack of documentation about this - it needs to be improved for sure.
The idea is that you provide a dataSource when instantiating the tree control, and that data source should have a data function with the signature (options, callback). That data function will be called on control init to populate the root level data, and will be called again any time a folder is clicked.
The job of the data function is to look at the options parameter which is populated from the jQuery.data() on the clicked folder and respond with the data for that folder. The special case is the initial root folder data, where the options are populated from any jQuery.data() on the control's root div, which may or may not exist.
The jQuery.data() on folders is populated from the array of objects you provide in your data function's callback. You can see in this example https://github.com/ExactTarget/fuelux/blob/master/index.html#L184-L189 there is a property called additionalParameters but really you can provide any additional properties beyond the required name and type for you to use later (the next time your data function is called) to determine which folder was clicked and return the data for that folder.
Our current example returns the same static data for every folder, which is not the best example, so I do hope to improve this situation by either creating a tutorial myself or linking to one if someone beats me to it.
Following up on Adam's answer, here is an example that seems to accomplish what you want..
The data function for the DataSource can check to see if there is "sub" data passed via options:
DataSource.prototype = {
columns: function () {
return this._columns;
},
data: function (options, callback) {
var self = this;
if (options.search) {
callback({ data: self._data, start: start, end: end, count: count, pages: pages, page: page });
} else if (options.data) {
callback({ data: options.data, start: 0, end: 0, count: 0, pages: 0, page: 0 });
} else {
callback({ data: self._data, start: 0, end: 0, count: 0, pages: 0, page: 0 });
}
}
};
Demo on Bootply: http://www.bootply.com/60761

Sencha touch store - phantom data

I created a model like
Ext.define('MyApp.model.ContainerDetailsModel', {
extend: 'Ext.data.Model',
alias: 'model.ContainerDetailsModel',
config: {
fields: [
{
name: 'id',
allowNull: false,
type: 'string'
},
{
name: 'container_types_id',
type: 'string'
}
]
}
});
and a store like this
Ext.define('MyApp.store.ContainerDetailsStore', {
extend: 'Ext.data.Store',
requires: [
'MyApp.model.ContainerDetailsModel'
],
config: {
model: 'MyApp.model.ContainerDetailsModel',
storeId: 'ContainerDetailsStore',
proxy: {
type: 'ajax',
enablePagingParams: false,
url: 'hereIsServiceUrl',
reader: {
type: 'json'
}
}
}
});
Now somewhere in application I tried to get one record like:
var detailsStore = Ext.getStore("ContainerDetailsStore");
detailsStore.load();
var detailsRecord = detailsStore.last();
But it gaves me undefined. The json returned by service is ok, it use it in different place as source for list. I already tried to change allowNull to true, but there is no null id in source. I tried set types to 'int' with the same result.
So I have tried
console.log(detailsStore);
Result is like this (just important values):
Class {
...
loaded: true,
data: Class {
...
all: Array[1] {
length: 1,
0: Class {
container_types_id: "1",
id: "726",
....
}
...
}
...
},
...
}
In the same place
console.log(detailsStore.data);
returns (as it should):
Class {
...
all: Array[1] {
length: 1,
0: Class {
container_types_id: "1",
id: "726",
....
}
...
}
but (next line)
console.log(detailsStore.data.all);
returns
[]
And it's empty array. When i try any methods from the store it says the store is empty.
I wrote console.log() lines one after another - so for sure it doesn't change between them (I try it also in different order or combinations).
My browser is Google Chrome 23.0.1271.97 m
I use Sencha from https://extjs.cachefly.net/touch/sencha-touch-2.0.1.1/sencha-touch-all-debug.js
How can I take a record from that store?
store.load() Loads data into the Store via the configured proxy. This uses the Proxy to make an asynchronous call to whatever storage backend the Proxy uses, automatically adding the retrieved instances into the Store and calling an optional callback if required. The method, however, returns before the datais fetched. Hence the callback function, to execute logic which manipulates the new data in the store.
Try,
detailsStore.load({
callback: function(records, operation, success) {
var detailsRecord = detailsStore.last();
},
scope: this
});

List not populating with a JsonP proxy

I want to have a Navigation view. I am trying to populate the list in Sencha Touch using a JsonP proxy.
Here's the sample code snippet of what I have tried till now :
var view = Ext.define('MyApp.view.NavigateView', {
extend: 'Ext.navigation.View',
xtype:'navigateview',
config : {
fullscreen:true,
styleHtmlContent:true,
scrollable:true,
items : [
{
title:'Navigation',
items : [
{
xtype:'list',
store: {
fields : ['title','author'],
proxy : {
type:'jsonp',
url:'https://ajax.googleapis.com/ajax/services/feed/load?v=1.0&q=http://feeds.feedburner.com/SenchaBlog',
reader: {
type: 'json',
rootProperty: 'responseData.feed.entries'
}
},
autoLoad:true,
},
itemTpl:'<div class="contact">{title} <strong>{author}</strong></div>',
listeners : {
itemtap : function(){
Ext.Msg.alert('Called');
}
}
}
],
}
]
}
});
But the problem is, my list is not getting populated. No items are being shown up in the list.
Also, I am constantly getting this error on console.
XMLHttpRequest cannot load
http://api.tinyhippos.com/xhr_proxy?tinyhippos_apikey=ABC&tinyhippos_rurl=list.php%3F_dc%3D1334462633038%26page%3D1%26start%3D0%26limit%3D25.
Origin http://localhost is not allowed by Access-Control-Allow-Origin.
Anyone please guide ? Anything that I am missing here ?
i was facing the same error when using AJAX request in cross domain.
have a look here
you have to make sure that the server part is configured properly using jsonp
as a first step identify if your application will run correctly when you disable web security in your browser
locate your chrome installation directory
then type in your cmd: chrome --disable-web-security
Your Ext.navigation.View object is containing one Ext.Component object (xtype not defined so defaulted to 'component') that is containing your list. If you put your list directly as an item of your view, it'll be rendered:
var view = Ext.define('MyApp.view.NavigateView', {
extend: 'Ext.navigation.View',
xtype: 'navigateview',
config : {
fullscreen: true,
styleHtmlContent: true,
scrollable: true,
items : [{
title: 'Navigation',
xtype: 'list',
store: {
fields: ['title','author'],
proxy: {
type: 'jsonp',
url: 'https://ajax.googleapis.com/ajax/services/feed/load?v=1.0&q=http://feeds.feedburner.com/SenchaBlog',
reader: {
type: 'json',
rootProperty: 'responseData.feed.entries'
}
},
autoLoad:true
},
itemTpl: '<div class="contact">{title} <strong>{author}</strong></div>'
}]
}
});
Note1: Not sure why your code is not working.
Note2: The error your mentioned is not related to your code snippet

Categories

Resources