I had to upgrade from 4.1.2 to 5.1.1 for the sole sake of widget columns. I'm having trouble getting hasone associations to work.
I've got a model that looks like this:
Ext.define('PP.model.LM.FOOModel', {
extend: 'Ext.data.Model',
requires: [
'Ext.data.field.Field'
],
fields: [
{
name: 'ID'
},
//Boatload of simple fields
],
hasOne: {
model: 'PP.model.LM.FOO1Model',
name: 'FOO1',
associationKey: 'FOO1'
}
});
When I interact with the model, there is no getter \ setter methods, and FOO1Model's data is only present as an object that can be accessed by
record.get('FOO1');
Could someone please point out what exactly am I doing wrong?
I tried doing it with the new approach - creating a field with a reference to the desired model. It works fine when I call setFoo1, and then do a get. But.
When I make an Ajax request, and try reading received JSON using Ext.data.reader.Json, it seems to fail to understand that a certain property in the object is in fact an associated model. The data in Foo1 appears in the model as an object in Foo1 property. The reqest returns an array of models that have many FooModels.
The Json looks like this:
{
"root": [{
"ID": 4241,
"Foos": [{
ID: 2237,
"Foo1": {
"ID": 1216
}
}]
}],
"success": true
}
It seems that hasOne doesn't exist in ExtJS 5.1 it is now done like this:
fields: [{
name: 'addressId',
reference: 'Address',
unique: true
}]
Check Model api for more info.
Had to debug the Ext.data.reader.Json to understand. The key was passing associationKey in reference config. Unless it's specified the reader will assume that the data for the association resides under '_foo1' field in JSON.
Is it mentioned anywhere in sencha docs? I don't think so. Am I supposed to feel like an imbecile for not guessing that?
Sample for unfortunate poor sods like me, who might encounter the problem in future:
{
name: 'Foo1',
reference: {
type: 'FOO1Model',
association: 'Foo1',
associationKey: 'Foo1'
},
unique: true
}
Related
My JSON data looks like this:
safarisDetails: {
loading: false,
safaridetails: {
safari: [
{
id: 1,
safari_name: '3 DAYS GORILLA TREKKING TRIP',
days: 3,
days_category: '<4',
budget: '900',
title: '3 DAYS GORILLA TREKKING TOUR',
text: 'Test.',
travelertype: '',
date_created: '2021-10-08T15:22:31.733347Z'
}
],
highlight: [
[
{
id: 1,
highlight: 'See the famous mountain gorillas',
safaris: 1
},
{
id: 2,
highlight: 'Get to know the Batwa community',
safaris: 1
}
]
]
I want to render objects in my component such as the safari_name and loop trough the highlights. However, when I use {safarisdetails.safari.safari_name} i get an error message stating: 'safari_name' is not defined.
There are a couple of problems based on the same you provided...
safarisdetails is repeated twice in the JSON, but not in your check
safari is an array in the JSON, but accessed like an object in your check
For example, to get the first name, you'd write something like:
safarisdetails.safarisdetails.safari[0].safari_name
Also, is this JSON even valid? Maybe you posted a partial snippet, but the JSON has to have {} around the whole thing.
I try to use Ext.Direct with the ExtJS 4 MVC structure, and I'm not able to add the provider.
I get the error Uncaught TypeError: Cannot call method 'addProvider' of undefined while calling addProvider:
Ext.Direct.addProvider(Ext.app.REMOTING_API);
I tried both in launch of the application and in initof the controller.
Ext.define('Dir.Application', {
require: [
'Ext.direct.*',
'Ext.data.*',
'Ext.grid.*'
],
launch: function(){
Ext.Direct.addProvider(Ext.app.REMOTING_API);
}
...
});
and
Ext.define('Dir.controller.Main', {
init: function(){
Ext.Direct.addProvider(Ext.app.REMOTING_API);
}
...
});
both give the same error.
Where is the correct location to put addProvider into the code ?
Update: applying the recommendations of #rixo.
Ext.define('Dir.Application', {
view:['Grid'],
requires: [
'Ext.direct.*',
'Ext.data.*',
'Ext.grid.*'
],
launch: function(){
Ext.Direct.addProvider(Ext.app.REMOTING_API);
}
...
});
My view is defining a store and a proxy:
Ext.define('Dir.view.Grid', {
extend: 'Ext.grid.Panel',
store: {
proxy: {
type: 'direct',
reader:{root: 'table'},
api: {
create: QueryDatabase.createRecord,
read: QueryDatabase.getResults,
update: QueryDatabase.updateRecords,
destroy: QueryDatabase.destroyRecord
}
}
...
}
Now the first error is OK, but I receiver an error complaining that QueryDatabase is not defined. It gets defined through the provider at Ext.Direct.addProvider(Ext.app.REMOTING_API); but it is not ready when the view is loaded through the views: [] declaration in the application definition.
Is there a way to get this working without nesting Ext.application inside Ext.onReady like in my solution?
No nesting would be better for the MVC way like explained here in the docs.
The require in your application definition won't do anything. It should be plural requires.
Also, you seem to have devised this in your own answer, but the name Ext.direct.Manager seems to be the favored by Sencha over Ext.Direct now.
Edit
According to the docs, you can set your direct functions using a string. Apparently, this is intended to solve exactly the kind of problems you've run into.
This should work and fix your issue:
api: {
create: 'QueryDatabase.createRecord',
read: 'QueryDatabase.getResults',
update: 'QueryDatabase.updateRecords',
destroy: 'QueryDatabase.destroyRecord'
}
Probably you are missing the API definition before calling the provider, take a look to this definition from Sencha's examples page
Ext.ns("Ext.app"); Ext.app.REMOTING_API = {
"url": "php\/router.php",
"type": "remoting",
"actions": {
"TestAction": [{
"name": "doEcho",
"len": 1
}, {
"name": "multiply",
"len": 1
}, {
"name": "getTree",
"len": 1
}, {
"name": "getGrid",
"len": 1
}, {
"name": "showDetails",
"params": ["firstName", "lastName", "age"]
}], ...}]
} };
It should be included as a javascript file inside your webpage
<script type="text/javascript" src="api.php"></script>
Something like this example.
Hope it helps.
Adding Direct providers is better done before the Application constructor runs:
Ext.define('Foo.Application', {
extend: 'Ext.app.Application',
requires: [
'Ext.direct.Manager',
'Ext.direct.RemotingProvider'
],
name: 'Foo',
constructor: function() {
Ext.direct.Manager.addProvider(...);
this.callParent(arguments);
}
});
Ext.application('Foo.Application');
I found this solution:
Ext.require([
'Ext.direct.RemotingProvider',
'Ext.direct.Manager',
'Ext.data.proxy.Direct'
]);
Ext.onReady(function(){
Ext.direct.Manager.addProvider(Ext.app.REMOTING_API);
Ext.application({
name: 'Dir',
extend: 'Dir.Application'
});
});
It doesn't look really nice, because it uses the ExtJS 4 application instantiation inside a Ext.onReady.
At least it works. Maybe there is a better solution ?
I don't have clear idea about extjs 'root' parameter in data store.
var xxx = new Ext.data.JsonStore
({
autoLoad: true,
url: 'www.dataserver.com',
root: 'data',
idProperty: 'ID',
fields: ['ID', 'Name']
});
i feel this very small thing but i'm very new to extjs please explain to me what is use for this root above data tore
It's a config of the JsonReader.
The JsonStore accepts all configs of JsonReader.
In the root config you give the name of the property that'll contain the array of row objects.
In your case it'll be :
{
data: [
{ID: 1, Name: "some name"},
{ID: 2, Name: "another name"}
]
}
Readers are used to interpret data to be loaded into a Model instance or a Store - often in response to an AJAX request. In general there is usually no need to create a Reader instance directly, since a Reader is almost always used together with a Proxy, and is configured using the Proxy's reader configuration property
Ext.create('Ext.data.Store', {
model: 'User',
proxy: {
type: 'ajax',
url : 'users.json',
reader: {
type: 'json',
root: 'users'
}
},
});
The above reader is configured to consume a JSON string that looks something like this:
{
"success": true,
"users": [
{ "name": "User 1" },
{ "name": "User 2" }
]
}
See in the above json structure, we have two attribute(with key:value pair) as "success" amd "users. The "users" key has array of object, which we are going to use in store. so in this json we are going to use the "users" attribute for our reader, so only we mention "users" as root for that store.
As recap, root is the config which will tell which part of attribute/object im going to use for my store in consume json.
Thanks
I am working in extjs4 MVC. I am getting stuck at a point where I have been working on association.Association is working properly when I am using in my system local side.But when I am uploading it to server side then the associated data is not displaying.I am trying a lot but not getting answer how this conflict occurs.
My application is working properly at client side.It displays associated data also.But when when I uploading data to server side then it does not display associated data.
Here is my application's some part which is working at local side:--
But when I am uploading my side to server side then the options means associated data is not displayed
Here Is my some code:--
1) Model class :--
Ext.define('B.model.kp.PollModel',{
extend: 'Ext.data.Model',
idproperty:'',//fields property first position pk.
fields: ['pollId','pollQuestion','isActive','pollTypeId','createDate','userId','publishDate','isPublished','approvalUserId','percentagevotes','optionId'],
hasMany:{
model:'B.model.kp.PolloptionModel',
foreignKey:'pollId',
name:'options',
},
proxy:
{
type:'ajax',
api:
{
read:'index.php/KnowledgePortal/Poll/GetPublicPoll',
create:'index.php/KnowledgePortal/Pollvote/setPollVote',
},//End of api
reader:
{
type:'json',
root: 'polls',
//successProperty: ,
},//End of reader
writer:
{
type:'json',
root: 'records',
//successProperty: ,
},
}//End of proxy
});
2) Store class :--
Ext.define('B.store.kp.PollStore',{
extend: 'Ext.data.Store',
model: 'B.model.kp.PollModel',
autoLoad: true,
});//End of store
3) View class:--
Ext.define('B.view.kp.poll.PollView',{
extend:'Ext.view.View',
id:'pollViewId',
alias:'widget.PollView',
store:'kp.PollStore',
config:
{
tpl:'<tpl for=".">'+
'<div id="main">'+
'</br>'+
'<b>Question :-</b> {pollQuestion}</br>'+
'<tpl for="options">'+
'<p>{#}.<input type="radio" name="{parent.pollId}" value="{optionId}"> {option}</p>'+
'</tpl></p>'+
'</div>'+
'</tpl>',
itemSelector:'div.main',
},
});// End of login class
4) here is my main view class
Ext.define('B.view.kp.poll.Poll',{
extend:'Ext.form.Panel',
requires:[
'B.view.kp.poll.PollView'
],
id:'pollId',
alias:'widget.Poll',
title:'Poll',
//height:180,
items:[
{
xtype:'PollView',
},
],//end of items square
buttons:[
{
disabled:true,
name:'vote',
formBind:true,
text:'vote',
action:'voteAction'
},
{
text:'result',
action:'resultAction',
}
]
});
5) And here is the json file --
{
'polls': [
{
"pollId": 1,
"pollQuestion": 'Who will win the match',
"options": [
{
"optionId":1,
"option":'India',
"pollId":1
},
{
"optionId": 2,
"option": 'Pakistan',
"pollId":1
},
{
"optionId": 3,
"option": 'Srilanka',
"pollId":1
},
{
"optionId": 4,
"option": 'Australia',
"pollId":1
},
],
}
]
}
6) PollOption model class :--
Ext.define('B.model.kp.PolloptionModel',{
extend: 'Ext.data.Model',
//idproperty:'',//fields property first position pk.
fields: ['optionId','option','pollId','percentagevotes'],
associations:[
{type:'HasMany', model:'Pollvotemodel', foreignKey:'optionId'},
{type:'BelongsTo', model:'PollModel', foreignKey:'pollId'},
]
});
Please someone give me some suggestion to solve this problem...
are you sure your server-side data feed is exactly the same as your local data feed.
Are the related questions entered into the live database?
I'm not able to describe my thought precisely in words, so here's an example:
[
{
'description': 'fruits',
'examples': [
{
'name': 'Apple',
'color': ['red', 'green']
},
{
'name': 'Banana',
'color': 'yellow'
}
]
},
{
'description': 'vegetables',
'examples': [
{
'name': 'Tomato',
'color': 'red'
},
{
'name': 'Carrot',
'color': 'orange'
}
]
},
{
'description': 'Wweets',
'examples': [
{
'name': 'Chocolate',
'color': ['brown', 'black', 'white']
},
{
'name': 'Candy',
'color': 'various'
}
]
}
]
Let's go step by step:
If I want to see all food categories, I query by the following command
db.food.find()
I want to see the vegetables
db.food.find({ 'description': 'vegetables' })
Now let's say I forgot how a Carrot looks like (lol). What do I do? I tried the following (Native node.js MongoDB driver):
collection.find({'examples.name': 'Carrot'}, function(err, example){
console.log(example)
// It still returns me the whole object!
});
As a result I expected MongoDB to return the next highest instance of the object. For example I wanted to do this.
console.log(example.color)
// 'orange'
Do you have any idea? I'm new to document oriented DBs :/
When you store a bunch of objects in a single document you will (by default) get back the entire document. [*]
When one of the fields of the document is an array, you will get back the full array if the item you are trying to match is found in the array.
Don't fall for the temptation to cram everything into a single document if you will normally be getting back only a subset of those things.
You have an alternative available:
You can store a collection of foods where every food has a field "type" which is "fruit" or "vegetable" or "...". You can still query for all foods, or just foods of type "fruit" or just food with name "carrot", etc.
Arrays are great for lists of attributes of a particular object/document, they are not as good when you cram documents into them that you then want to get back as first-class objects.
[*] there is a way to project and get only a subset of the fields, but you will still get back entire fields.