I'm trying to get the massload plugin to work with my jstree configuration. The nodes are built as Country->City->Site->Product->License. When the tree is loaded initially, only the top level nodes are loaded (in my case Countries). When a user expands a node, the children are loaded using ajax. I have a search box that searches in the tree, this works, but it only matches on nodes that are already loaded. I would like to this to work on all site level nodes, loaded or not.
The search ajax call to returns a list of site ids, which is passed to the massload plugin. It calls the LazyLoad method with the correct ids. What I'm can't figure out is what to return in response to the massload call. According to this, it should take the form of
{
"id1" : { "id" : node_id_of_child1, "text" : "child2", "id" : node_id_of_child2, "text" : "child2" },
"id2" : { ... node data ...}
}
Where id1 and id2 are matching node id's from the search.
But when I do that, the nodes aren't added to the tree and the search term only matches on nodes already loaded.
This is my jstree configuration
$('#tree').jstree({
core: {
data: {
url: '#Url.Action("Nodes", "Home")',
data: function (node) {
if (node.id === '#')
return {
nodeType: 'root'
};
else
return {
nodeType: node.data.type,
nodeValue: node.data.value
};
},
type: 'POST'
}
},
plugins: ["massload", "search"],
search: {
"show_only_matches": true,
ajax: {
url: '#Url.Action("Search", "Sites")',
type: 'POST'
}
},
massload: {
url: '#Url.Action("LazyLoader", "Home")',
data: function (nodes) {
return { "ids": nodes.join(",") };
},
type: 'POST'
},
themes: {
"theme": "default",
"dots": false,
icons: true
}
});
Questions:
- Is the response format from the massload ajax call correct?
- What is the massload plugin's action based on this response? Should it try to load the nodes in the response in the same way (i.e. using the same ajax call) the nodes are loaded when a user requests them?
Related
I have this test relay-starter-kit project with an autocomplete search form that renders quotes to the browser. When I use the search form, I get an error in the browser saying "app.js:8284 Uncaught TypeError: Cannot read property 'edges' of undefined". I cant understand why its populating the search fields the first time but not on typing in the search form. Of note, if you hard code the searchTerm variable, it will render the search results. In other words, It can read the edges when its hard coded. Any guidance on this would be great. Thanks.
The schema is here
This is the component that the valid graphql query for the search term wont render to.
import React from 'react';
import Relay from 'react-relay';
import { debounce } from 'lodash';
import SearchForm from '../search-form';
import Quote from '../quote';
class App extends React.Component {
constructor(props) {
super(props)
this.search = debounce(this.search.bind(this), 300)
}
search(searchTerm) {
this.props.relay.setVariables({ searchTerm });
}
render() {
return (
<div className="quotes-library">
<SearchForm searchAction={this.search} />
<div className="quotes-list">
{this.props.viewer.quotes.edges.map(edge =>
<Quote key={edge.node.id} quote={edge.node} />
)}
</div>
</div>
)
}
}
export default Relay.createContainer(App, {
initialVariables: {
searchTerm: '',
},
fragments: {
viewer: () => Relay.QL`
fragment on User {
quotes(first:100, searchTerm: $searchTerm) {
edges {
node {
id
${Quote.getFragment('quote')}
}
}
}
}
`,
},
});
Update: This is the query as shown in Chrome DevTools network tab. Note the 'p' input to the search form is being queried.
query App_ViewerRelayQL($id_0:ID!) {
node(id:$id_0) {
...F2
}
}
fragment F0 on Quote {
id,
likesCount
}
fragment F1 on Quote {
text,
author,
id,
...F0
}
fragment F2 on User {
_quotes3UfnML:quotes(first:100,searchTerm:"pri") {
edges {
node {
id,
...F1
},
cursor
},
pageInfo {
hasNextPage,
hasPreviousPage
}
},
id
}
Adding console.log to render() shows the searchTerm input:
app.js:17
{
"viewer": {
"__dataID__": "VXNlcjox",
"__status__": 4
},
"relay": {
"pendingVariables": null,
"route": {
"name": "AppHomeRoute",
"params": {},
"queries": {}
},
"variables": {
"searchTerm": "pri"
}
}
}
The following error occurs at line 24 in app.js, which is {this.props.library.quotes.edges.map(edge =>
<Quote key={edge.node.id} quote={edge.node} />
)}:
app.js:8285 Uncaught TypeError: Cannot read property 'edges' of undefined
at App.render (app.js:8285)
at app.js:43197
at measureLifeCyclePerf (app.js:42476)
at ReactCompositeComponentWrapper._renderValidatedComponentWithoutOwnerOrContext (app.js:43196)
at ReactCompositeComponentWrapper._renderValidatedComponent (app.js:43223)
at ReactCompositeComponentWrapper._updateRenderedComponent (app.js:43147)
at ReactCompositeComponentWrapper._performComponentUpdate (app.js:43125)
at ReactCompositeComponentWrapper.updateComponent (app.js:43046)
at ReactCompositeComponentWrapper.receiveComponent (app.js:42948)
at Object.receiveComponent (app.js:35341)
UPDATE 2:
So check this out. I'm doing something wrong with my { ObjectID }. I pulled a user and quote from the db and there is an '_id' but no 'id' property on the object. This is the output:
> db.users.find({})
{ "_id" : ObjectId("586253169465191cb812066c"), "name" : "me", "id" : ObjectId("586253169465191cb812066c"), "errors" : [ ] }
> db.quotes.find({})
{ "_id" : ObjectId("586693333ff93f3581c0ca05"), "text" : "Hi Prisc", "author" : "H. Jackson Brown", "likesCount" : 24 }
{ "_id" : ObjectId("586693333ff93f3581c0ca06"), "text" : "If opportunity doesn't knock, build a door", "author" : "Milton Berle", "likesCount" : 2 }
{ "_id" : ObjectId("586693333ff93f3581c0ca07"), "text" : "Try to be a rainbow in...", "author" : "Maya Angelou" }
If I log the id from the globalIdFetcher(), the logged id for the Jackson Brown Quote object show two id's as expected but they are both the same and different from the one in the db. Output in console is:
{
"viewer": {
"__dataID__": "VXNlcjo=",
"quotes": {
"__dataID__": "client:6068631311_first(100),searchTerm()",
"edges": [
{
"__dataID__": "client:client:6068631311:UXVvdGU6NTg2NjkzMzMzZmY5M2YzNTgxYzBjYTA1",
"node": {
"__dataID__": "UXVvdGU6NTg2NjkzMzMzZmY5M2YzNTgxYzBjYTA1",
"id": "UXVvdGU6NTg2NjkzMzMzZmY5M2YzNTgxYzBjYTA1",
"__fragments__": {
"1::client": [
{
"showLikes": false
}
]
}
}
},
Any ideas on fixing this syntax?
It's very difficult to solve the problem with the information provided in question. As you requested guidance, here's my suggestions :)
I cant understand why its populating the search fields the first time but not on typing in the search form.
Because Relay fetches the result for the initial value of searchTerm, which is an empty string in your case. You have to deal with this case on the server side (by checking the input searchTerm) and client side (by checking if the current value of searchTerm is empty, for example).
When you type in search form, search() isn't called and searchTerm is not updated. Check SearchForm component.
When I use the search form, I get an error in the browser saying "app.js:8284 Uncaught TypeError: Cannot read property 'edges' of undefined".
Start debugging what the server side returns for quotes field under viewer GraphQL object type. What's the output of db.collection('quotes').find(findParams).toArray() in your schema? In addition, put a console.log(JSON.stringify(this.props, null, 4)) in render() function of App class. Check what you see. You can also inspect the HTTP request and response on the Chrome DevTools Network tab. Filter by graphql.
Solution was to take the Quote type out of the nodeInterface so only running the top level object through the nodeInterface, let relay generate the id for the objectId from the GraphQLID or fromGlobalId as defined in the individual itemType.
I found this example to use the Node API to apply filters to related models, but I was wondering if it was possible to achieve the same result using REST?
Node Example:
Post.find({
include: {
relation: 'owner', // include the owner object
scope: { // further filter the owner object
fields: ['username', 'email'], // only show two fields
include: { // include orders for the owner
relation: 'orders',
scope: {
where: {orderId: 5} // only select order with id 5
}
}
}
}
}, function() { ... });
The closest version of a REST url I can get to work is:
...?filter[include][owners][orders]
Is it possible to create a REST url that behaves the same way as the above Node example, by limiting the results based on a related model filter... in this case orders?
I have this functions so when I call the Hdates/coming REST API it shows the events with date greater than today and also includes the venues... Hope it helps.
Hdate.coming = function(cb) {
Hdate.find({
where : {
event_date :{gt: Date.now()}
},
include : {
relation: 'event',
scope : {
include: {
relation: 'venue'
}
}
}
}, cb);
};
Hdate.setup = function() {
Hdate.base.setup.apply(this, arguments);
this.remoteMethod('coming', {
description: 'Find Coming Events by Date',
returns: {arg: 'events', root: true},
http: { verb: 'GET' }
});
};
Hdate.setup();
i have an "back end" application which write in MongoDb (in database i have _id: with ObjectId("13f6ea...002")) i use meteor app to show information. Everything was good i displays list of information with {{#each}}. But when i wanted show one element with '_Id' nothing works.
I read this issue and adapt my code to get right root, But i can't display anything on the page. I tried to write Template helpers but it didn't helped
Db record:
{
_id: ObjectId("13f6ea...002"),
url: "foo",
title: "bar",
published: "2014-08-22 03:26:21 UTC",
image: "foo.jpg",
summary: "foo ",
categories: [
"F",
"B"
],
...
}
Route:
this.route('news', {
path: '/news/:_id',
template: 'news',
waitOn: function () {
var id = this._id;
Meteor.subscribe('news', id);
},
data: function() {
var id = this.params._id;
return News.findOne({ _id: Meteor.Collection.ObjectID(this.params._id)});
},
action : function () {this.render();},
});
Publish
Meteor.publish('news', function(id) {
return News.find({_id: id});
});
Template which redirect to unique post
<h4>{{title}}</h4>
And template is just {{news}}
How can i fix this?
UPDATE
My solutions to fix that:
router.js
waitOn: function () {
var id = this._id;
Meteor.subscribe('News', id);
},
data: function() {
return News.findOne(new Meteor.Collection.ObjectID(this.params._id));
},
and in template
<a href="news/{{_id._str}}">
Navigate to the appropriate url in your browser (i.e. localhost:3000/news/[_id]), open the console and enter:
Router.current().data()
That will show you the data context of the current route. Either it returns nothing, in which case there is a fundamental problem with your News.findOne query as it's returning nothing, or (more likely) it returns the required document.
In the latter case, as far as I can see there is no news property within that document, which is why it isn't rendering anything. If you change {{news}} to {{url}} or {{summary}} I would imagine it would render the requested property.
If by {{news}} you're trying to render the entire document, then (aside from the fact that it will render as something like [Object]) you need to make news a property of the object returned by your data function:
return {
news: News.findOne({ _id: Meteor.Collection.ObjectID(this.params._id)});
};
Getting Document with _id :
In the .js file under events, Say on click event and Collection EventList :-
'Submit form' : function () {
var id = this._id;
return EventList.find({_id : id}).fetch();
}
This would return the object for the id. In my Case, I am displaying a field for all documents in Collection. User selects a record and clicks Submit, which fetches all Document fields and displays to the User
I've been trying to retrieve a date value and an integer value from the database, using the following code:
var l_alsChampsMois, l_stoDonneesMois;
try {
l_alsChampsMois = [
{name: "date_mois", type: "date", dateFormat: "Y-m-d"},
{name: "indice", type: "integer"}
];
l_stoDonneesMois = new Ext.data.JsonStore({
fields: l_alsChampsMois,
autoLoad: false,
proxy: {
type: "ajax",
url: "/commun/req_sql/req_ind_per_mois.php",
reader: {
type: "json",
root: "rows"
},
// some configs to use jsFiddle echo service (you will remove them)
actionMethods: {
read: "POST"
},
extraParams: {
key:"test"
}
},
listeners: {
load: function(objStore, alsLignes, blnOk, objOptions) {
window.alert("Mois fin : " + objStore.getAt(0).get("date_mois"));
}
}
});
l_stoDonneesMois.load({params: {
p_idsoc: l_strIdSociete,
p_mois: l_datDebut.getMonth() + 1,
// getMonth renvoie 0 pour janvier, etc.
p_annee: l_datDebut.getFullYear(),
p_debut: 1,
p_etape: 1
}
});
with l_strIdSociete and l_datDebut being variables previously assigned and /commun/req_sql/req_ind_per_mois.php the PHP page that retrieves the data and converts it to JSON.
It seems to work fine (indeed, Firebug tells me the load does retrieve a data structure with "date_mois" and "indice" containing the values I expect them to), only the window.alert returns undefined. If I replace "date_mois" with "indice", it returns the expected value for "indice".
I've tried to use objStore.getAt(0).getData()["date_mois"], to no avail.
My only clue about this is that "date_mois" in the data structure shown by Firebug is an Object, but even so it shouldn't be undefined, now should it? I looked up http://docs.sencha.com/ext-js/4-1/#!/api/Ext.data.Field-cfg-type that wasn't exactly forthcoming with straight answers.
So what did I do wrong there?
If you need current time you can use php time function(note: it returns seconds, JS uses milliseconds), in another case you need to convert by mktime function.
I am using EXTJS and SERVLET, in servlet I am passing the value through request.setAttribute,
But not able get the value in EXTJS.
Ext.onReady(function(){
var myData=null;
Ext.Ajax.request({
url: 'DisplayTest',
method:'POST',
success: function ( result, request ) {
myData =Ext.decode(result.responseText);
},
failure: function ( result, request) {
Ext.MessageBox.alert('Failed', result.responseText);
}
});
var store = new Ext.data.ArrayStore({
fields: [
{name: 'name'},
{name: 'id'},
]
});
store.loadData(myData);
// create the Grid
var grid = new Ext.grid.GridPanel({
store: store,
columns: [
{
// id :'company',
header : 'Name',
width : 160
},
{
header : 'ID',
width : 75
},
],
height: 350
});
grid.render('db-grid');
});
In above code I want to get the value from servlet into variable myData in the form of array or List.
can anyone give me some example through servlet and EXTJS.
Thanks
You will not be able to pass the data directly from Servlet using request.setAttribute. Use the formPanel.getForm().load() method to pass the request to the servlet. This method requires a JSON object in the response: something of the form:
{ success: true, {
name: "Andy",
dob: "11-12-1987"
}
}
You can either send this data through the PrintWriter.write() function or use the JSON API in the servlet which directly gives the json string based on the data provided to the API.