I'm new to Extjs4.2/OL/Geoext2 developing, and I'm confused about how it should work.
--- edit ---
I'm trying to write a small app to read GeoJSON, place read features on the map, let the user to edit them / draw new ones, and finally save them back to GeoJSON.
My current approach:
OpenLayers.Layer.Vector is bound to Geoext.data.FeatureStore.
Layer reads GeoJSON, and FeatureStore is populated.
And now my question - how to save the modified by user data to GeoJSON?
I can save the data as JSON by FeatureStore, but I don't see an easy way to make FetureStore save GeoJSON. Should I use vector layer to save GeoJSON, or try to add some type of conversion to add geometry attributes of the features to FeatureStore, and then sync() the store?
--- edit ---
Already done this by inserting another attribute to the model:
{
name: 'geom',
convert: function(value, record) {
return record.raw.geometry.toString();
}
}
Now my FeatureStore saves GeoJSON-like output with geometry, which is ok for me.
Question: Is it the right way to do this?
Regards, Pawel
I'm not an expert, but I think GeoExt.data.FeatureStore was created to be synchronized with the layer. So, if you do a store.sync() no update request will be sent to your remote GeoJSON data source. GeoExt.data.FeatureStore constructor starts by creating a proxy: { type: 'memory', ... and thus your original proxy will be replaced by this one. To use the GeoExt.data.FeatureStore you have to rewrite it.
So, I think the best way to do this is to use a OpenLayers.Protocol.Script source, which is quite flexible, configured to use your remote GeoJSON source. Using the layer's save strategy, all updates will be sent to the remote source.
Regards!
Related
This is a design question.
I'm trying to build a booking system in cakephp3.
I've never done something like this with cake before.
I thought the best way might be to -- as the post title suggests -- build up an entity over several forms/actions.
Something like choose location -> enter customer details -> enter special requirements -> review full details and pay
So each of those stages becomes an action within my booking controller. The view for each action submits its content to the next action in the chain, and i use patch entity with the request data, and send the result to the new action's view.
I've started to wonder if this is a good way to do it. One significant problem is that the data from each of the previous actions has to be stored in hidden fields so that it can be resubmitted with the new data from the current action.
I want the data from previous actions to be visible in a read only fashion so I've used the entity that i pass to the view to fill an HTML table. That's nice and it works fine but having to also store that same data in hidden fields is not a very nice way to do it.
I hope this is making sense!
Anyway, I thought I'd post on here for some design guidance as i feel like there is probably a better way to do this. I have considered creating temporary records in the database and just passing the id but i was hoping I wouldn't have to.
Any advice here would be very much appreciated.
Cheers.
I would just store the entity in the DB and then proceed with your other views, getting data from the DB. Pseudo:
public function chooseLocation() {
$ent = new Entitiy();
patchEntity($ent,$this->request->data);
if save entity {
redirect to enterCustomerDetails($ent[id]);
}
}
public function enterCustomerDetails($id) {
$ent = $this->Modelname->get($id);
// patch, save, redirect again ...
}
I want to make property read-only. When I am creating Vertex in DB i want to set property value and do not allow update in future. Is there any possible solutions on DB side? Or I have to do it in my scala Back-end? What is the best practise? Thx Lot.
My back end solution:
/Schem
mgmt.makePropertyKey("guid").dataType(classOf[java.lang.String]).make()
mgmt.makePropertyKey("propFoo1").dataType(classOf[java.lang.Long]).make()
mgmt.makePropertyKey("propFoo2").dataType(classOf[java.lang.Long]).make()
mgmt.makePropertyKey("propFoo3").dataType(classOf[java.lang.Long]).make()
mgmt.makePropertyKey("propFoo4").dataType(classOf[java.lang.Long]).make()
mgmt.makePropertyKey("propFoo5").dataType(classOf[java.lang.Long]).make()
In controller for Update method:
// Map of no changeable atb
val vertexEntityOld = EntityController.findByGuid(newEntity.guid.toString())
newEntity.propFoo1 = oldEntity.propFoo1
newEntity.propFoo2 = oldEntity.propFoo2
Titan has the notion of static vertices; that's the only thing that comes close to what you want. But read-only properties are not supported out of the box, that's something your application code has to take care of.
I am working on extjs 4 MVC application.
Application runs the Viewport, which contains tabpanel.
Each tab has own controller and multiple views.
See my sandboxs at http://wap7.ru/folio/ext-reuseable-store/TE.html
I have one Store used several times (e.g. one tab in topmenu combobox, another in the clietns grid.)
Store configured with autoload: true.
Proxy is configured in the Model.
My problem: Store is loaded multiple times - at every mention in the controller [stores] array.
If I remove one from the array [stores] controller- combobox will be empty, although it states store: Ext.getStore ('STORE-ID')
Please give me a hint, or an example of re-using Store (not Model) as in here http://docs.sencha.com/ext-js/4-0/#!/guide/mvc_pt2
You can just instantiate your store and load it, remove the autoload.
var store = Ext.create('App.store.YourStore').load();
Then pass that store to all your components, just like you would do when you want a paging bar connected to a grid.
This normally works fine to call your store from other controllers:
Ext.getStore('PlatformClient');
I've never tried to put the same store in more than one controller stores array. That seems strange to me.
There are a couple of other oddities about the code you have posted though, maybe they're just typos and maybe they don't make any difference to the framework but they're different from what I normally do so I'll point them out:
First, your model array in the "typical controller" contains a store:
models:[
'te.store.PlatformClient'
],
That one is probably just a typo.
Second, I don't put the full namespace in my store arrays, this is something that may not make a difference, but I don't know. Maybe ExtJS is prepending the namespace on top of the namespace you have written out so it thinks that you are instantiating a different store whenever it initializes a new controller - thereby causing it reload. For example this is more "normal" for whatever it's worth:
stores:[
'Taxonomy',
'PlatformClient',
'DataType'
],
controllers:[
'Taxonomies' ,
'DataType' ,
'DataSale' ,
'Clients'
],
Try setting it up like that and get rid of the duplicative stores in the other controller store arrays.
Also, I want to make sure that you caught the bit in the docs about not needing to define a storeId config for MVC stores. The framework will automatically give the store this:
storeId: [StoreClassName]
So in your example, you would get this automatically:
storeId: 'PlatformClient'
Someone else had trouble with MVC stores recently and it traced back to the framework being flabbergasted by the audacity of the dev supplying their own storeId config with the MVC pattern.
We used to have similar problems with loading. Also got issues with filtering in case of multiple use of the same store (you may want to set filter on one but not on the other). Therefore we load all the stores at application launch. Then whenever we need that store for displaying purposes then instead of using the original we are cloning it in the memory with ha utility function as below.
/**
* Use this for example if you want to apply a filter on a store
* but you dont want the original store to change, so:
* singleton store has no filter
* you clone it to be used with filters in some places.
*
* Note: this will have memory proxy, so no changes to the stores are persistent,
* changes will have no effect on the local/remote db.
*
*/
createStore: function(storeId, data) {
//
// Creates a new store from the given array of records without
// registering the new store.
// See cloneStore for more info
//
var modelName = storeId;
var prevStore = Ext.getStore(storeId);
data = data || prevStore.data.all;
var clonedStore = Ext.create('App.store.' + storeId, {
data: data,
model: 'App.model.' + modelName,
proxy: 'memory'
});
Ext.data.StoreManager.register( prevStore );
return clonedStore;
}
Please note the cloned copy is using memory proxy. Therefore write operations shouldn't be done on it. If you need to update the store then always use the original.
I hope this helps on some way.
I'm using a store to fetch the specializations of all hikers (so hiker has many specializations). However, I have a detail window where this specializations are added/removed/shown ony for currently selected hiker (yea, it's a detail window).
My problem here is that my store fetch data for all hikers, but I want it to show, when detailed window is up, only data for given hiker. Notice also that I'm showing data in data-grid, so the user possibly can add filters and I noticed that if I add a filter with store.filter({...}) and user add a filter with data-grid, my filters are removed (so basically they are useless.
Which approach should I use? Do you have any suggestion? I were thinking about 1 store for each hiker, but I don't like this solution.
Edit 1:
I also noticed that I can't create a filter in the same way as data-grid builds them:
Ext.create('Ext.util.Filter', {
type: 'numeric',
comparison: 'eq',
field: 'hiker_id',
property: 'hiker_id',
value: me.hiker.get('id'),
root: 'data'
})
Which is boring, because I imnplemented on server side a functionality that parses the grid filters already.
We just give our filters in json format to the store's extra params. And parse that back-end. The extra params stay the same while paging or refreshing the grid.
grid.getStore().getProxy().extraParams = { filter: yourFilter };
-How- are your users doing the filter?
store.filter accepts both arrays and functions, so you can do quite a bit with it, without actually juggling the data on the server. (eg manage an array that is being passed to the filter, test against an object somewhere, or whatever)
Permanent filter? Not so much, but since you can add multiple filters etc, it is relatively trivial to keep track of what filters are in place.
http://docs.sencha.com/ext-js/4-1/#!/api/Ext.data.Store-method-filter
Scenario: I have a URL that returns details about the current logged in user. I.e.
one record
no list needed
Options I have:
Perform a manual ExtJS Ajax call each time, having to insert the code everywhere I need the callbacks etc.
Create an ExtJS Store once and fetch the first record from the store instance every time.
Question: Any better options? I'm using ExtJS 4.1.
You don't need to go into low level details to do something like that; use the standard tools. Define a Model, assign it a Proxy of the type you need, and load it. See the docs: http://docs.sencha.com/ext-js/4-1/#!/api/Ext.data.Model
Why are you doing an ajax call each time?
Do it once, and assign it as a global variable?
Ext.Ajax.request({
url: 'page.php',
params: {
id: 1
},
success: function(response){
var text = response.responseText;
window.user = Ext.JSON.decode(text);
my.custom.launchFunction();//does your viewport etc for you
}
});
Having done this, you can now, from anywhere do
console.log(user.Name);
Its neater, and faster, than doing a store lookup.
As a bonus, you user object can be much more complex than the store would handle without a ton of config.