sfExtjsTheme plugin
PLEASE NOTE, THIS PAGE NEEDS A BIG UPDATE!
LOTS OF INFO IS OUTDATED! MOSTLY DUE TO THE IMPLEMENTATION OF A NEW SYNTAX FOR THE GENERATOR, WHICH IS ABLE TO PROCESS FOREIGN FIELDS (columns from related tables), by providing the foreign-key/related-column-name, as can be seen in the overview, slightly below.
the syntax has changed to foreign_key/field_name (instead of foreign_table/field_name).
Live Demos :
- http://fun4me.demon.nl/test/test_dev.php/city (source attached in this wiki, install sfExtjs2Plugin and sfExtjsThemeplugin, change database and propel config-files, outdated!!! old syntax... should be foreign_key/field_name instead of foreign_table/field_name)
- http://tejohnston.dynora.eu/backend_dev.php/ (admin:admin)
See also: http://www.symfony-project.com/forum/index.php/m/37256/#msg_37256
The sfExtjsThemeplugin extends the power of the generator (see below at features) and adds the ExtJS AJAX library to a symfony project, while remaining (almost completely) compatible (with exception of the first 2 features) to the default symfony-theme. It allows you to use the power of the ExtJS library for the admin generated modules by simply defining this theme and its generator in your generator.yml file.
Extjs version 2.1 is implemented. I've also used Silk-Icons from Mark James, but I don't know anymore if I still use it (it now still is included).
This is still a very alpha-alpha release ;) Based on the initial work of Wolfgang Kubens who initialised the idea and DrCore? (Andre Schuurman) who provided his nice work to get foreign values. My work was about he development of the generator and this is improved by Jérôme. Currently KRavEN and lukas are actively using and enhancing this plugin.
We currently have been added to the trac-ticket-system: http://trac.symfony-project.com/query?component=sfExtjsThemePlugin&order=priority
The new generator-syntax, and what is generated.
Have fun, Leon
Installation
Get the files
TODO: (does not work yet) $ symfony plugin-install http://plugins.symfony-project.com/sfExtjsThemePlugin
NOW: For now, you have to do a SVN checkout/update: $ svn co http://svn.symfony-project.com/plugins/sfExtjsThemePlugin/
and make a symlink from you web folder to the plugin-webfolder, like:
cd web ln -s ../plugins/sfExtjsThemePlugin/web/ sfExtjsThemePlugin
Configuration
or by simply copying the contents of the plugins/sfExtjsThemePlugin/web/ folder to /web/sfExtjsThemePlugin
- Change your class in the generator.yml file from sfExtjsPropelAdminGenerator to: sfExtjsPropelAdminGenerator
- Change your theme in the generator.yml file from default to: extjs
generator:
class: sfExtjsPropelAdminGenerator
param:
theme: extjs
...
...
- The specific Extjs libraries are loaded automatically!
TODO: option to disable it (so you still are required to do this manually) TODO2: maybe smaller/optimised version can be loaded
You probably also want to change your projects default main.css to:
ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,body,html,p,blockquote,fieldset,input
{ margin: 0; padding: 0; }
a img,:link img,:visited img { border: none; }
a
{
text-decoration: none;
}
a:hover
{
text-decoration: underline;
}
body, td
{
margin: 0;
padding: 0;
font-family: Arial, Verdana, sans-serif;
font-size: 11px;
}
body
{
padding: 20px;
}
- Clear the cache
$ symfony cc
INSTALL FROM SVN IN EXISTING SVN PROJECT
: If you are already using subversion for your project, the correct way to include the sfExtjsThemePlugin repository is to define svn:externals Go to your symfony project
svn propedit svn:externals plugins
in this file add
sfExtjsThemePlugin http://svn.symfony-project.com/plugins/sfExtjsThemePlugin/
This way, every time you use svn update, it will get the latest version of sfExtjsThemePlugin from the symfony repository
Dependencies
This plugin needs the sfExtjs2Plugin to work (http://trac.symfony-project.com/wiki/sfExtjs2Plugin)
Notes
- there is a howto in svn which tells you how to start from a standard sandbox: http://svn.symfony-project.com/plugins/sfExtjsThemePlugin/HowTo%20Sandbox.txt
Troubleshooting
Apparently there is a problem (http://extjs.com/forum/archive/index.php/t-12615.html) when you are using latest prototype together with Ext Js. Make sure to disable the prototype plugin on pages you are using sf ext.
Since the update you need the sfExtjs2Plugin (dependancy)
Features
Distinction between new and edit
Exception 1 of being fully backward compatible...
The title of the edit-page has two titles:
- one title for editing and item
- one title for adding a new item
edit:
title: Edit city "%%name%%"
newtitle: Add a new city
When newtitle is not set, the default will be "Add a new <class-name>"
Default actions
Exception 2 of being fully backward compatible...
I changed the behavior of the default action of the edit-page to "Save and List" (instead of "save and edit (again)"), I think this better suits the expectations of a user. The list is giving the feedback of a successfull save-action. You can of course overrule this by defining the actions of your edit-page in your generator.yml file.
Also the "Create" button below your list has been changed. The caption of it now shows "Add new <class-name>".
Multisort lists
You can have your list been sorted on multiple columns at the same time. You can set the default sort order of multiple columns in your generator. The order in which you define them is important, the first item in the sort-list is the first column on which gets sorted.
PLEASE NOTE: EXTJS DOES NOT SUPPORT SORTING ON MULTIPLE COLUMNS YET, see below in TODO2. If you set ajax: false multisort does work.
Add multisort: true to your list options in your generator.yml
An example of how to sort cities first on country, then on city-name:
list:
title: Cities
multisort: true
sort: [[country, desc], name]
If you want to define to one default sort column, you should keep the nested array, so for example:
list:
title: Cities
multisort: true
sort: [[name, asc]]
Because ascending is the default value to sort on,
list:
title: Cities
multisort: true
sort: [name]
is valid as well. In these cases the user has the ability to sort on multiple columns at the same time.
Please note that in the first example I sort on country, and not on countryid, see new feature: Sort on foreign- and composite-columns. However new functionality in the list (grid) with drop-down combo-boxes reintroduces countryid. If you use country you will not have a drop-down combo-box! setting the sort-field for countryid remains useful in this case.
TODO: Currently the filter-reset button also resets the sort-order, but I think it would be nice to have a seperate reset button for it. And I also think the reset should reset the sort-order to the generator.yml file default settings, not to no-sort-order at all which is currently the case...
TODO2: The Extjs-grid does not support the visual feedback in its multi-sort-column-header. It does work because the sorting is done on the server, but your column-header shows only the sorting of the last column you sorted on. I think it should be possible to overwrite the default behavior of the extjs-column-header and make it behave like http://tablesorter.com/docs/ (holding shift to sort on multiple-columns). This does however requires some extra work on the php-code, to make it reset the sorting when you don't hold shift. Multisorting isn't working with ajax set to true, because at the moment extjs cannot handle sorting on mulitple columns. It can only sort one column at a time. If you disable ajax (ajax: false) you can see how it should work. Someone first has to extend extjs with this functionality before this is possible. I very much like the implementation done with jquery: http://tablesorter.com/docs/ (holding the shift-key while pressing the column headers to sort on multiple columns) It should be possible to extend extjs with this functionality, but it is not there (yet). At the moment I haven't got time for this yet. And to make it work like the jquery example, there should also be some extention for my plugin, to make the multi-sort reset when you don't hold shift.
Sort on foreign- and composite-columns
You can now also sort your columns on columns with foreign-values or composite values (from multiple/different columns, like full-names which are combined in a partial). You have to add some information to the generator.yml file to define the sort-order though, it can't do magic (yet)...
TODO: This gets/is? replaced by Andre's work. you should define something like country/name instead of country or countryid (which use the toString() method, which is limiting). This way you also don't have to define the sort_column and join_fields anymore
list:
title: Cities
display: [ =name, country ]
filters: [ countryid ]
fields:
country:
join_fields: [CityPeer::COUNTRYID, CountryPeer::COUNTRYID]
sort_column: CountryPeer::NAME
If you use the ajax view, you can now also display countryid and see an inline combo-box in the list, when you edit it.
Group by
Todo: fix this, it currently is broken....
With Ajax you have the option to group you list on columns, you do this by setting the group_field option in your generator.yml file under list. When you have not set a sort column, the column which you define here will be used, which is recommended!
generator:
class: sfExtjsPropelAdminGenerator
param:
model_class: City
theme: extjs
list:
title: Cities
multisort: true
sort: [ country, name ]
display: [ =name, country ]
filters: [ countryid ]
grouping:
field: country
plugins: summary
fields:
name:
summary_type: 'count'
summary_renderer_function: "return ((v === 0 || v > 1) ? '<b>' + v +' Countries</b>' : '<b>1 Country</b>');"
country:
join_fields: [CityPeer::COUNTRYID, CountryPeer::COUNTRYID]
sort_column: CountryPeer::NAME
The summary plugin can be defined by a partial, in which you can write your javascript helper. In this case the total under every group (The number of cities under a country) will be count.
TODO: Sorting with a grouped grid is an issue, need testing! (groups can possibly show up multiple times on different pages)
Master-detail pages
Todo: this feature is currently broken.
You can now define master-detail relationships between modules. In the generator.yml file you define the detail-module and its field- and display-options.
Example, where an Assignment can contain multiple parcels: (sorry my classes and fields don't always have underscores)
generator:
class: sfPropelAdminGenerator
param:
model_class: Assignment
theme: extjs
sub_class:
model_class: Assignmentparcel
display: [ =subject ]
fields:
subject:
name: Parcel
summary_type: 'count'
summary_renderer_function: "return ((v === 0 || v > 1) ? '<b>' + v +' Parcels</b>' : '<b>1 Parcel</b>');"
fields:
sf_guard_user_related_by_created_by:
name: Created by
sf_guard_user_related_by_updated_by:
name: Updated by
list:
title: Assignments
multisort: false
display: [ subject, vessel, sf_guard_user_related_by_created_by, created_at, sf_guard_user_related_by_updated_by, updated_at ]
grouping:
field: subject
plugins: summary
fields:
vessel:
join_fields: [AssignmentPeer::VESSELID, VesselPeer::VESSELID]
sort_column: VesselPeer::NAME
In this example you see the grouping field is defined, but it is optional. If you leave it out, the first field of your main-diplay-list is selected. I think sub_class speaks for itself.
TODO0: At the moment I cannot get an instance of sub_class. I now have copied the code from several symfony methods and placed it in the plugin, this is far from optimal of course. I am also not able to find if fields of a sub-class are foreign-keys to other tables, which makes it impossible to let them appear as drop-down combo-boxes.
TODO1: I have to think about mixing the fields of the main_class and the sub_class. (although all fields in a main-column will be the same for a group) TODO2: Maybe it is possible to define the generator.yml file of the sub_class in the master-generator.yml file, instead of this sub_class list.
Drop-down Combo-boxes in the list
Thanks to the work of Andre you can have drop-down boxes at the location of foreign-values (for example a dorp-down list of countries next to a city).
It works like this:
generator:
class: sfExtjsPropelAdminGenerator
param:
model_class: City
theme: extjs
ajax: true # true by default
fields:
name:
name: City
country/name:
name: Country name
params:
editable: true
country/abbreviation:
name: Abbreviation
params:
editable: true
list:
title: Cities
display: [ =name, country/name, country/abbreviation ]
filters: [ countryid ]
By default the fields in a list are not editable, to make the fields editable you can set this with the params option, or you can change the default option to true in your app.yml settings file.
Default options
You can define default options in your app.yml file.
all::
...
sf_extjs_theme_plugin:
ajax: true
list_max_per_page: 15
list_editable: true
Disable the Extjs functionality
If you want to disable the ajax functionality and only make use of the other new functionalities like the multi-sort feature, you can disable the ajax functions in your application yml file:
app.yml
all::
...
sf_extjs_theme_plugin:
ajax: false
list_max_per_page is the other option, which can be set application-wide.
These options can also be defined in the generator.yml file to define it per module. E.G. add the option ajax: true in your generator.yml (at the same level as theme, css, list) file to overwrite the ajax option from your application settings for a specific module.
generator:
...
param:
theme: extjs
ajax: false
...
...
TODO:... Work in progress.
- Namespace of javascipt in list and edit pages should probably also contain the moduleName (DONE), so multiple modules can be loaded in the same page (E.G. Pop-ups). I think that at the momement you now dynamically load new modules in your page, They overwrite the current load/edit page javascript. Maybe also optimalisations can be made which check if reloading is necessary (for example list and edit pages probably share the same related data stores...)
- Fields with Foreign values are shown as drop-down boxes with autocomplete features. It is also possible to define new values, but the event handlers are not perfect yet (far from it). Partly due to the Ext-Js library. This needs some work.
- Drop down combo-boxes also have a problem when the data-store is empty. They do not recognize the value they hold and the drop-down and autocomplete is broken at that moment. Stores always need to contain at least the value the current drop-down is showing (which can be done by a onFocus event or something, which makes the store add/load the correct (pre-loaded) json-data)
- The plugin dependeds on the sfExtjs2Helper plugin, but more code needs to use this plugin
- the add new foreign-object window which appears after typing a unknown foreign-value has a cancel button, which closes the current active tab.... This should of course be the current add-new-foreign-object window... This cancel button should also make the drop-down-combo-box discard the newly entered value.
- you cannot use a field both as group-by-field and column in your grid. This will make drop-down comboboxes not working (see city/country-name)
- Fix handeling partials and components (For JSON-Data and in getColumnAjaxTag), partly done, need optimisations (remove line-breaks and more testing)
- Improve filtering (need drop-down combo-boxes)
- Fix (multi)-sorting on columns (need ExtJS - javascript extention, Multi-sort is not visible in column-header, limitation of Extjs library which can be extended with javascript (but has not been done, maybe check extjs-forum and ask overthere))
- Edit-pages can be split up into several tab-pages, but this needs some improvements (E.G. namespaces and form-names might need to change)
- Improve configurability: more values should loose the hardcoded-part so they can be set (like column width, footer on/off, footer text, etc.)
- Improve peer_method, currently join-all is used to minimise the number of queries automatically, but you some want this be disabled by default, nice would be to have auto-detection for foreign-fields (easy) and than set join-all if nothing else has been defined. Even better would be to not call join-all, but join-all-that-I-need, but this probably requires changing the data-model-lib from the generator...
- Include UNIT-TESTING, but how??? advice/start up greatly appreciated.
- Update the readme and sandbox-howto
- More documentation, for now see: http://www.symfony-project.com/forum/index.php/m/37256/#msg_37256
- Master-detail with multiple linked grids: like http://www.symfony-project.org/forum/index.php/m/42011/#msg_42011
Attachments
- test.zip (193.3 kB) -
City-Country source
, added by Leon.van.der.Ree on 02/07/08 19:27:04. - test.tgz (87.4 kB) -
newer version of the city-country example
, added by Leon.van.der.Ree on 04/16/08 19:38:18. - generator.yml (11.5 kB) -
Documentated generator.yml file
, added by Leon.van.der.Ree on 04/16/08 19:39:18.
