I am using the Telerik.Web.Mvc.UI Grid to show a grid on an Asp.Net MVC website.
All of the columns are supposed to be sortable / filterable, but as you will see from the image below, the only who that actually do have a Sort / Filter in the right place are the File Name column and the Project Requested By column.
These columns are bound by the following code...
c.Bound(o => o.FileName);
c.Bound(o => o.Dto.ProjectDetailsDto.ProjectRequiredBy)
.Template(o => o.Dto.ProjectDetailsDto.ProjectRequiredBy.HasValue ? o.Dto.ProjectDetailsDto.ProjectRequiredBy.Value.ToString(Model.DateTimePattern) : "")
.HeaderHtmlAttributes(Resources.EditorLocalization.ProjectDeadline);
Let's limit the problem, and ask ourselves why the Project Name is not sortable (it isn't). The project name is bound like so :
c.Bound(o => o.Dto.ProjectName)
.Template(o => Html.ActionLink(o.Dto.ProjectName, "Details", "Project", new { projectId = o.Dto.AssetTask.ProjectId }, null))
.HeaderTemplate(Resources.EditorLocalization.ProjectName)
.Sortable(true)
.Filterable(true);
First of all, I considered that it might be that columns that use a template cannot be sorted - only they can, because we have the working case of the Project Required By Column.
Perhaps, I thought, it is the presence of the HeaderTemplate() that is causing us problems, but then why would it? Still, I can't deny, everything I believe should work, but doesn't, has a HeaderTemplate.
So - let's blame that and see what we can do... The reason I am using a HeaderTemplate is because we want to be able to be able to localise the strings used to label the columns (ie the headers). Is there any other approach we might take which would allow us to do that, but also mean we could have sorting on the grid as well?
Thanks in anticpation...
Ok - the problem was indeed down to my use of HeaderTemplate(). If I use the Title() method instead, all is well...
Related
I'm in a project that uses Symfony 1.2 (I know this is quite old, but I can't do anything about this).
I have a sfWidgetFormPropelChoice widget which feed its options from a foreign key than exists say in table A. I would like to group that foreign key since another column in table A, with the optgroup HTML element.
So I have something like that:
$this->widgetSchema['B_has_A_list'] = new sfWidgetFormPropelChoiceMany(array(
'model' => 'TableA',
));
And I would like to have something that easy:
$this->widgetSchema['B_has_A_list'] = new sfWidgetFormPropelChoiceMany(array(
'model' => 'TableA',
'optgroup' => 'ColumnInTableA', //That's not possible. It would group options grouping by ColumnInTableA using the optgroup HTML element
));
Do you know another easy way to achieve this. Or do you know any extended sfWidgetFormPropelChoice that achieve this?
Thank you.
Ok, I extended the symfony widget to achieve this. If anybody is interesed, it's in github:
https://github.com/laMarciana/sfWidgetFormChoiceOptgroup
To use you have to define the same required options than sfWidgetFormPropelChoice plus a optgroup_columnoption with the PhpName of the column you want to use as the optgroups.
Ex:
$this->widgetSchema['field'] = new sfWidgetFormPropelChoiceOptgroup(array(
'model' => 'Table',
'optgroup_column' => 'Column',
));
I added as well a version for Doctrine.
I have a telerik MVC grid. After making some changes to the underlying code, the grid no longer shows the results returned from the server. I can see the correctly formatted JSON return from the server (using functionality from Web Developer Toolbar), but the grid never actually shows the data. However, it also doesn't generate an error. The loading icon just keeps spinning.
Does anyone have a suggestion on how to localize the problem? Thanks.
EDIT
Well, I managed to get a step further. Apparently something goes wrong in the "bindData"-function located in telerik.grid.js. More specifically in line 462:
460. var evaluate = column.display;
461. if (evaluate)
462. html.cat(evaluate(data[rowIndex]));
When trying to render the last column in the first row, evaluate is set to anonymous and somehow, this results in an "invisible" exception. The markup of this column is:
columns.Bound(c => c.DocumentId)
.ClientTemplate("<a href=\"" + Url.Content("/") +
"/document/<#= DocumentId #>\" target=\"_blank\"><#= Naam #></a>")
.Filterable(false)
.Title("Naam");
I don't understand why this would be a problem, as I use similar templates elsewhere without any problem.
EDIT
Ok, I got it. Apparently some exceptions will not be shown in the Firefox/Firebug console. However, Visual Studio together with IE do not have this problem. I finally discovered that indeed the field "Naam" was missing in the IEnumerable.
So something to take away here is never to trust the results from just one browser ;-)
I had a similar behaviour recently when I had changed the type that the grid was expecting.
Make sure that your ajax call is returning the correct IEnumerable that is specified in the grid markup.
You need to post code for the GridAction and markup if you want a more accurate answer.
I have a contact, and contact has_many :phones. The phones table has a column named, phones_desc, where I want to include the type of phone number the user has saved.
My question / Best practice
Should I provide a select with manually provided options (such as "mobile", "work", "home")...
-or-
...create a new model named phones_types where I can add the values I'd like, thus creating a unique ID for each one. Then I can do the following after changing phone_desc to phone_type_id, adding phones has_many :phone_types and giving the phone_types table a name column:
#phone = Phone.first
#phone.type.name
Sidenote
I'm currently doing it with the first option (not a separate model) and am having trouble with it selecting the value when I go to edit the parent object. In other words, the select options don't have the saved value selected when going to edit phone numbers.
It always has the first option selected, so the user may inadvertently change the phone_desc without realizing it.
If the first option is in fact the better way to go, would you have any insight on how to get the objects value to be the selected value when editing phones descriptions via a select?
I'd still go for a separate model for the phone type. This way, you can more easily add other phone types later on. Also think about i18n, it might save you some headache when translating "Mobile" to Japanese.
Turns out that option one works just fine, and I can get the selected option to work too. It was a problem in the order that I supposed the option parameters.
I changed:
<%= f.select :number_desc, '<option value="mobile">Mobile</option><option value="work">Work</option><option value="home">Home</option><option value="other">Other</option' %>
to:
<%= f.select :number_desc, [["Mobile", "mobile"], ["Work", "work"], ["Home", "home"], ["Other", "other"]] %>
And voila - selected works fine. :)
I'm using Symfony 1.4 and Doctrine.
Let's say I have 2 classes : a Brand and a Product.
When I create a new product in the Admin Generator based admin, I'd like to choose a brand from a dropdown list.
The Admin Generator is doing that for me, automatically creating a sfWidgetFormDoctrineChoice.
The problem is that the brands are ordered by id. I'd like them to be ordered by their "label" field.
In order to do that I did the following in my ProductForm class:
$this->widgetSchema['brand_id']->addOption('order_by','label');
But I get the following error:
Syntax error or access violation: 1064
You have an error in your SQL syntax;
check the manual that corresponds to
your MySQL server version for the
right syntax to use near 'a' at line
1. Failing Query: "SELECT b.id AS b__id, b.external_id AS
b__external_id, b.label AS b__label,
b.created_at AS b__created_at,
b.updated_at AS b__updated_at FROM
brand b ORDER BY l a"
The order by statement is really weird. I don't understand why it seems to cut the name of the order by statement.
Edit: Apparently the 'order_by' option is expecting an array as a second parameter. What values does it expect?
I didn't try benlumley's solution since he answered right when I found my solution. It seems more tedious than what I ended doing.
I took a look at the source code to figure out how all this was working.
It turns out the "order_by" option needs an array specifying the field on which one wants to order the results and either 'asc' or 'desc':
$this->widgetSchema['product_id']->addOption('order_by',array('label','asc'));
It works like a charm.
You should take a look here:
http://trac.symfony-project.org/wiki/HowtoSortAdminGeneratorListByForeignTableName
Its based off of an old version of symfony, so suspect the plugin it links won't work. But I think the method should still be sound - crux of it is that you have to add method to the action to intercept and amend the default handling of sorting by this specific field:
For doctrine, you need to define/override addSortQuery, for propel, addSortCriteria.
Recommend you take a look in the cache folder to see what the auto-generated classes look like to get the hang of how it works.
While I do find that the PHP Symfony framework is wonderful for many things, I am finding it difficult to create easily scalable dynamic menus for a website.
I am wondering how other Symfony developers out there have dealt with this issue.
I will give a simple example as to what I am asking.
If go to www.fool.com you will see that they have a typical menu setup. A list of categories with one of them being the active one that is in some way highlighted with CSS.
What would be a good way to make this dynamically created in a Symfony project. Passing variables of some sort from module to module. I have not yet found an elegant solution.
Generally, I just manually build an array of module/action combinations that I'd like to appear in my menu. It'd be fairly easy to grab this information from a dynamic source (like a configuration file, or a database):
$this->menu = array(
'Home' => array('default', 'index'),
'About Us' => array('default', 'aboutUs'),
'Products' => array('products', 'index')
);
Then, I use the controller's getActionName and getMethodName methods to determine which item in my menu is the current one:
$this->current = array_search(array($this->getModuleName(), $this->getActionName()), $this->menu);
Then I can iterate over $menu, from within the template, to build up the menu. And I can compare the items with $current, to determine whether I should set a "current" class on the menu item's <li>.
The fool.com example you give is a bit more complicated, because it's two level. In that case, you'd probably want to be generating your menu tree from a database, perhaps making use of Propel's nested set support.