This plugin returns edit and list panels, which are extensions of the Ext.Panel Object.
The generator can handle foreign-fields, and allowes to define properties from the Ext-api with the params parameter in your generator.yml (for fields, list, edit and pages)

Developers

License

TODO... Open-Source but with respect to the Extjs licensing model and Creative Commons Attribution 2.5 License for the Silk-icons...

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

sfExtjsTheme plugin

THIS PAGE IS BEING REWRITTEN

sfExtjsTheme plugin

Hello All,

if you are user, or not (anymore) of this plugin, would you please help me and fill in my little poll and give some feedback which I can use for my master-thesis: [http://www.symfony-project.org/forum/index.php/m/56847/]

Thanks in advance,

Leon

Introduction

The sfExtjsThemeplugin is just like the name says a theme plugin for ExtJS in Symfony. With this plugin you can generate list and edit ExtJsPanel-objects from your generator.yml file, all you have to do after installation of this plugin is simply defining this theme and its generator in your generator.yml file.

The plugin extends the power of the default generator (see below at features) and uses the sfExtjs2plugin in order to include the ExtJS AJAX library to a symfony project, while remaining (almost completely) compatible to the default symfony-theme.

Currently Extjs version 2.1 is implemented (with a tiny hack, registered xtype-checking).

Also included are the Silk-Icons from Mark James.

Features

This plugin currently has the following features:
* Administration generation capable of handling foreign values
* Distinction between new and edit panels (different titles, different actions)
* Sorting (multi-sort not supported by ExtJS grid yet)
* Grouping
* Mater-detail overviews (like grouping, but including empty groups)
* Capable of Lazy-loading its libraries (with the help of the 'Using' script)

You might also want to take a look at:
* the sfAjaxWebDebugPlugin in order to see the symfony debug-toolbar updated with every ajax-request
* the sfCombineFilterPlugin latest version from KRavEN, to be able to combine and minify your included javascript and css

Future wannahave is probably going to be:
* the sfPropelFinder in combination with Propel 1.3
* we are also working on a gui-editor for the yml files, but this has just been started: sfExtjsThemeGuiPlugin not functional at all yet!

DEMO

In this wiki at the bottom you can find a demo attached: sfExtjsThemeExample.tgz (the other files (test and generator.yml) are OBSOLETE, but I cannot remove them...)

you have to checkout the latest version from sfExtjs2Plugin and sfExtjsThemePlugin (svn co http://svn.symfony-project.com/plugins/sfExtjsThemePlugin/ or svn export http://svn.symfony-project.com/plugins/sfExtjsThemePlugin/) yourself... (since these are quite large)

you should also add a cache and log folder and execute "symfony fix" to set the correct file/folder-credentials

Maybe you also have to restore the symlinks from the webfolder to the plugins/web-folder

After that setup the database in the config/databases.yml and config/propel.ini files, of course setup your database itself and prepare your web-server.

TODO: you are of course allowed to move these items I've added to other examples...
TODO: explain and define (new) actions
TODO: explain xtypes, renderers and renderers

You obviously cannot sort custom_methods, since they aren't part of your database. There are two solutions to solve this:
1. The easiest is to define a different field to sort on, as shown in the example above (under fields a sortField has been set) However at the moment you cannot define multiple sortFields for one column (for example first FirstName then LastName) from the generator.yml. To solve this you have to override your actions.class.php. Also the key "Combo" in the generator.yml will probably change in the future.
2. Define a custom column in your query by changing your objects Peer-method. This way your database will do the sorting.

Globals in app.yml and in generator.yml

TODO: Explain the app.yml

# default values
all:
sf_extjs_theme_plugin:
theme: gray # extjs theme
list_max_per_page: 40 # used for both grids and combos
module_returns_layout: false # set to true to let the module return a layout (so you don't have to setup a layout.php) or let the module only return a js-var: App.RequestedModulePanel
module_panel_name: App.RequestedModulePanel # the name of the var to the panel name returned by the module-action
list_editable: true
list_tabbed: false
open_panel_handler: App.openPanelHandler # a method which accepts the event and target from the event-handler the event-object contains the moduleName and item's-key, if this method is not defined, the grids url will open as normal ( window.location will be changed).
open_panel: App.openPanel # a method which accepts the moduleName and item's-key, if this method is not defined App.openPanel create-buttons from the list will change the window.location
use_tinymce: true
format_date: "D d-m-y"

This plugin contains a app.yml in its config folder. When you want to make changes to its default values, copy the app.yml from the plugin/config folder to your project\app\config folder (or merge it with the one you already have). This to prevent problems when updating the plugin.

Overriding Globals in generator.yml

TODO: Explain which globals can be redefined on generator level.

Tabpanel & Gridpanel Sections: Create your own Panels

TODO: separate these two, tabs are way different from grids, there isn't any similarity.... maybe better is to explain the difference between tabpanel and edit.pages (from the generator.yml file)

What is the difference between a tabpanel and a gridpanel?
Here are some examples:

The tabpanel consists of the following tabs and the corresponding content:

edit.pages can do this:

And this is a gridpanel:

Here's an tabpanel section that overrides the onRender method:

# Starts defining the tabpanel
tabpanel:
# Number of Active Tab, defaults to 0
activeTab: 0
# Contains all methods to be added or overridden
method:
# Partials contains functions and variables
partials: [_beforeUpdate ]( _onClose,)
# onRender is the function name and the parameters are the same as the sfExtjs2 as method
onRender:
parameters: ct, position
# Here is place for code
source: |
MainLayout.getCenter().remove(0);
MainLayout.getCenter().add(this).show();
MainLayout.getLayout.doLayout();
variable:
numItems: 100
# Place for plugins such as Java plugins
plugins: [new Plugin() ]( App.plugin,)

Fields Section: Outlining the fields

The fields section contains the definition of all fields used in the generator. This is what you can use as fields:
* Database fields of course, like defined in schema.yml
* ORM methods: E.G. a $sfGuardUserProfile->getFullName which returns the values of the first_name and last_name fields delimited by a space.
* Partials that implement an xtype.

Combos for Related fields and methods

Foreign columns are always shown as combos in list grids or edit forms. There are three kinds of combo's available:
* The Ã¯Â»Â¿Ext.ux.form.ComboBox as known from Extjs.
* The Ext.ux.ComboBoxAutoLoad which comes with a store of your possible FK values.
* The Ext.ux.grid.ForeignFieldColumn is not a combo! It is a column designed for foreign-fields, which automatically sets up a renderer, can use preloaded values (transport items from grid/form-datastore to combo-datastore) and can setup the combo-store, displayfield, valuefield, etc

The default is to use the ComboBoxAutoLoad. This can be changed in app.yml.

Combos can be configured with many paremeters. In the example below their all implemented. The comboConfig parameter can include every configuration option of your combo xtype.

// Question: Everytime I define a combo like above, it does not work on edit panels... why?

// Question: How can I remove the "Add new" and "Modify" labels on the combo? (the possibility to add to the user)
// LEON: at the moment you cannot, These combos will be improved soon

// Question: How can I control if the value of fullName can be emptied (no fullname assigned)? I could add an emptied store to the dataset serverside... can I trigger that also with required true | false? A: At the moment not implemented. Generator will add an emptied set when required: false.

Combos for Sets of values

Many times your user has to choose between a set of values. Not every time this values are worth an own table. Sometimes it's enough to let the user choose between a fixed set of values.

You can do that by defining a combo for a non-FK field. Important when you do this is to add the "store" parameter to your fields params, and set the mode (in comboConfig) to local:

Editable is set to false and pageSize to 0 by default for such a kind of combo.

Field Partials and Xtypes

TODO: An Example partial and all the configs for it.

Modify the view with Renderers

Most values are not saved in the DB as displayed in your application. Let's say you have a table "product" with a weight. Now when you display the weight in your application, you most likely want the weight to be shown as "10 kg" (lbs/gr whatever). When you save the weight in the database, you save a number (like 10.0) whitout the unit declaration.

To solve this with sfExtjsThemePlugin you can use renderers in your field definitions:

Icons

We have included the Ext.ux.IconMgr which can be used to include icons, see the examples above to see how.

If you want to include your own custom icons you can make a symlink from "plugins/sfExtjsThemePlugin/web/Ext.ux.IconMgr/icons/[application-name]" to your applications "web/images/icons"-folder.
That way you can include an icon like:

Application Layout

The ThemePlugin generates two kind of panels, which both are extentions of the ordinary Ext.Panel ( http://extjs.com/deploy/dev/docs/output/Ext.Panel.html )
For every module you will get a list-gridpanel and an edit-formpanel, these panels can be used in any way you want, you don't even have to have a full extjs layout (with for example a viewport http://extjs.com/deploy/dev/docs/output/Ext.Viewport.html )

panel = {
xtype : 'list' + modulename + 'gridpanel'
};

Simply define the xtype-name of your-modules panel when defining the viewport/panel-items and you will see the item on your screen.

You also don't have to include the pjs-source as a javascript-include in your header for your panels, the plugin will find the source automatically for you during runtime (lazy loading).

You can also have a gridpanel as a field your edit-panel, or link an edit-panel to your grid. I would advise you to continue defining the layout in your app.js just like you can see in the demo. So seperate html and js(-layout)

key is used to pass the primary-key, if undefined you will get a create panel.

To get the item which you requested by url (so index.php/module/action ) you can use the App.RequestedModulePanel (which simply contains an instance of the panel with its xtype (and key when it is an edit-action) set.

at the moment you will also get a editpanel (without form) which is a wrapper around the formpanel, this will probable become obsolete. Also at the moment there isn't yet a panel for filtering, this should be defined in the future as well, but this is still a todo. If anyone can make one I will merge it with the plugin. This filter-panel can be based on the source for grid and form-panels (gridpanel source is somewhat nicer, edit-panel with its form-layout is what you want for filter-panels.

Tips

Development

Knowledge needed

TODO: Link this
To develop with this plugin you need knowledge about this things:
* sfExtjs2Plugin
* Extjs and xtypes
* Symfony view layer (partials )

Best approach for fast results

TODO: Provide a few steps to create a basic application with at least 2 tables (e.g. ToDo with categories)

Start with a minimal generator.yml and....

Debugging

Debugging your sfExtjsThemePlugin code is like debugging two applications: A PHP application on the server-side and a client-side Extjs JavaScript application. Therefore you need tools and knowledge to debug both of them and all the communication between them.

Debugging Tools

You can enable the symfony debug toolbar, to enable it install the sfAjaxWebDebugPlugin

The syck addon is somewhat more strict in checking your json files, so please check your syntax well, I had to remove a in app/config/filters.yml after security: since I have a class defined underneath it.

For xcache you might want to add the second line:

xcache.admin.enable_auth = Off
xcache.admin.auth = On

to /etc/php5/conf.d/xcache.ini

Additional Concepts

I18n

Credentials

Known Bugs / Issues

See also Trac: http://trac.symfony-project.com/query?status=new&status=assigned&status=reopened&status=closed&component=sfExtjsThemePlugin&order=status

lukas who is also constantly using and testing this plugin, added some improvements and now provides resources for documentation

lvanderree (Leon) and that will be me. Probably main developer of this plugin

Besides credits need to be given to:
* Jack Slocum together with the ExtJS team, for providing this great Javascript framework.
* Jozef Sakalos, aka Saki for proving great insight in how to develop nice applications in Javascript/ExtJS
* Doug Hendricks for his work on Managed-IFrame and the basex-library.
* Andrew Mayorov for his work on the TinyMCE integration in ExtJs
* Jay Garcia for his work on the Ext.ux.TDGi.iconMgr (which we renamed to Ext.ux.IconMgr)

to:
* Jon Davis for his 'Using' script which made the first version of lazy loading Javascript-libraries possible

and to:
* Mark James for his Silk-Icons.

BELOW ARE ALL OLD TEXTS

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.

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

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 "

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 ".

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: [desc], name]([country,)

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: [asc]]([name,)

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

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!

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).

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.

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 (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