I am using propel and i set two behaviours onto one of my tables:
<behavior name="archivable" />
<behavior name="i18n">
<parameter name="i18n_columns" value="name" />
<parameter name="default_locale" value="de" />
</behavior>
The problem is, that if I archive an object of that table then the field "name" is not saved. Apparently in the "copyInto" Method of the Base-Class there is no
$copyObj->setName($this->getName());
Is that a bug in propel or am I missing somethhing here?
You have to archive the i18n information manually by making the table archivable, too, and by overriding the generated archive() method. An example is given in the Propel blog:
class Book extends BaseBook
{
public function archive(PropelPDO $con = null)
{
// archive the book reviews
BookReviewQuery::create()
->filterByBook($this)
->archive($con);
// archive the current object
return parent::archive($con);
}
}
source: http://propel.posterous.com/introducing-archivable-behavior-and-why-softd
Related
index.xhtml
<p:selectOneMenu id="d2" value="#{mainManageBean.areaSelected}" >
<f:selectItem itemValue="" itemLabel="Select one" />
<f:selectItems value="#{mainManageBean.areaList}" var="area"
itemValue="#{area.id}" itemLabel="#{area.name}"/>
<p:ajax event="valueChange" listener="#{mainManageBean.changeAreaSelect()}" update="hi" />
</p:selectOneMenu>
When i have value set like this "mainManageBean.areaSelected" where areaSelected is entity from database
private Area areaSelected;
the ajax event dont work,
but when i change it to something like this "mainManageBean.s1menu" where this "s1menu" is just a normal String ajax event work fine.
What is the reason of that and how to fix it?
Edit
this is my buged converter:
#FacesConverter
public class areaConverter implements Converter{
#Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
// here i have problem value is id of entity and have no idea how to get this entity form this id
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
// works fine value = Area entity
#Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
if (value == null || value.equals("")) {
return "";
} else {
return String.valueOf(((Area) value).getId());
}
}
}
Have problem with getAsObject, i have this value as id but cant get entity from it. Normaly i would use AreaFacade.find(id) but i cant use there #EJB to get it.
First of all, your <f:selectItem itemValue> is wrong. It should represent exactly the same type as <p:selectOneMenu value>, which is thus Area. Replace itemValue="#{area.id}" by itemValue="#{area}". You indeed need a Converter for this.
As to your problem with the converter,
Have problem with getAsObject, i have this value as id but cant get entity from it. Normaly i would use AreaFacade.find(id) but i cant use there #EJB to get it.
you have 2 options:
Make it a #ManagedBean #RequestScoped instead of #FacesConverter and reference it as converter="#{areaConverter}" instead of converter="areaConverter".
Install OmniFaces >= 1.6. It adds full transparent support for #EJB inside #FacesConverter without any additional configuration or annotations.
If you go the OmniFaces path anyway, then you could also just throw away your custom converter altogether and go for its builtin SelectItems(Index)Converter without the need to create any custom converter for itemValue="#{area}".
<p:selectOneMenu ... converter="omnifaces.SelectItemsConverter">
See also:
CDI Injection into a FacesConverter
You are trying to set an Entity with value of ID, I assume Integer or String? The reason why ajax does not fire is because event="valueChange" does not occur. If you tried to submit this form without ajax you would get a sweet ClassCastException. As I mentioned in my comment and Makky in his answer, change itemValue to:
<p:selectOneMenu id="d2" value="#{mainManageBean.areaSelected}" >
<f:selectItem itemValue="#{null}" itemLabel="Select one" />
<f:selectItems value="#{mainManageBean.areaList}" var="area"
itemValue="#{area}" itemLabel="#{area.name}"/>
<p:ajax listener="#{mainManageBean.changeAreaSelect()}" update="hi" process="#this />
</p:selectOneMenu>
As per comment from Kuba
<f:selectItems value="#{mainManageBean.areaList}" var="area"
itemValue="#{area.id}" itemLabel="#{area.name}"/>
change itemValue as
<f:selectItems value="#{mainManageBean.areaList}" var="area"
itemValue="#{area}" itemLabel="#{area.name}"/>
Update:
The other thing it could be the converter. My suggestion is to use the SelectItemsConverter from Onmnifaces.
Omnifaces select item converter
I have a SqlDataSource defined in my aspx file that I use to call a StoredProcedure. It takes a hiddenField as its control parameter.
<asp:HiddenField ID="input" runat="server" />
<asp:SqlDataSource ID="source" runat="server"
ConnectionString="<%$ ConnectionStrings:ConnectionString %>"
SelectCommand="sp" SelectCommandType="StoredProcedure">
<SelectParameters>
<asp:ControlParameter ControlID="input" Name="input" Type="String" />
</SelectParameters>
</asp:SqlDataSource>
Is there a way I can grab that parameter from the ViewState instead? Preferably while keeping the datasource definition in the aspx file.
The solution in your case is very easy. Just create your own class inherit it from Parameter and override Evaluate method.
[DefaultProperty("ViewStateKey")]
public class ViewStateParameter : Parameter
{
public string ViewStateKey
{
get
{
return (string)ViewState["ViewStateKey"] ?? string.Empty;
}
set
{
if (ViewStateKey == value)
return;
ViewState["ViewStateKey"] = value;
OnParameterChanged();
}
}
protected override object Evaluate(HttpContext context, Control control)
{
if (control == null || string.IsNullOrEmpty(ViewStateKey))
return null;
return ViewState[ViewStateKey];
}
}
After that you will be able to use your parameter like following (just remember to register it at the top of your page or in web.config):
<asp:SqlDataSource ID="source" runat="server"
ConnectionString="<%$ ConnectionStrings:ConnectionString %>"
SelectCommand="sp" SelectCommandType="StoredProcedure">
<SelectParameters>
<my:ViewStateParameter Name="input" Type="String" ViewStateKey="input" />
</SelectParameters>
</asp:SqlDataSource>
And your parameter will get its value from viewstate by key input.
I dont feel that the code for ViewStateParameter is of the first class. Maybe you will want to decorate it with more attributes and/or extra parameter checks with assertions.
I have similar problem. I dont want to use hidden fields to bind data source parameters because of security reasons.
I have googled one work-around - use asp:label instead of hidden field (make sure Visible=false). And then your label goes to view state and you can bind label to data source parameters.
I don't have the experience of working with Helpers so I am bit stuck in using a code at hand.
My requirement is simple and all I need is optgroup functionality in DropDownListFor extension method. While searching, I came across this Answer and have copied this as it is in a file named MyExtensionClass.cs.
But, I don't know how to use this or call the extension method defined in this. Please tell me how can i use this with my list.
Right now, following is the controller code for a selectlist for which i want to use the extension methods.
ViewBag.ParentCategoryId = new SelectList(db.Categories, "Id", "Name");
And this is my view code
#Html.DropDownListFor(model => model.Product.CategoryId,
(IEnumerable<SelectListItem>)ViewBag.CategoryId, "---Choose Category---",
new { #class = "required" })
Please help me upgrade this to extension method with optgroup.
We use Serge Zab's helper for optgroup dropdowns. Here is a sample:
The viewmodel:
public class OurViewModel
{
public int? TypeId { get; set; }
public IEnumerable<GroupedSelectListItem> GroupedTypeOptions { get; set; }
}
The controller:
public ActionResult Add()
{
var model = new OurViewModel
{
// fill with initial values
};
PutTypeDropDownInto(model);
return View(model);
}
[NonAction]
private void PutTypeDropDownInto(OurViewModel model)
{
model.GroupedTypeOptions = _repos.GetTypes()
.OrderBy(t => t.Category.EnglishName).ThenBy(t => t.EnglishName)
.Select(t => new GroupedSelectListItem
{
GroupKey = t.Category.RevisionId.ToString(),
GroupName = t.Category.EnglishName,
Text = t.EnglishName,
Value = t.RevisionId.ToString()
}
);
}
The view
#Html.DropDownGroupListFor(m => m.TypeId, Model.GroupedTypeOptions,
"[Select a type]")
Note that you can't use a regular SelectList. You have to use a collection of his GroupedSelectListItem class. Also, our solution doesn't use viewbag. The dropdown list is strongly typed on the viewmodel.
Update
To get the html helper to work in your view, the view needs to be able to find it. You can either add a #using directive at the top of the view with your MyExtensionClass.cs namespace, or add the namespace to the view-specific web.config, like so:
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="Microsoft.Web.Mvc" />
<add namespace="Namespace.For.MyExtensionClass" />
</namespaces>
</pages>
This was added to ASP.NET MVC at version 5.2!
Property Group in SelectListItem allows you to specify a group for each item
Html.DropDownList() and DropDownListFor() now generate optgroup elements based on the groups included on the list of items.
I'm running Joomla 1.7 and I know that it has the ability to add custom form fields to components with a plugin.
There is a sample plugin located at:
/plugins/user/profile
This plugin allows you to put custom form fields on the user profile front end and back end and these fields are stored in a custom table.
I created a similar plugin for user profiles and it worked perfectly.
However, when I go to create a plugin like this for com_content, I am met with a problem.
this is what my XML file looks like:
<?xml version="1.0" encoding="utf-8"?>
<form>
<fields name="additionalinfo">
<fieldset name="additionalinfo_fieldset" label="PLG_CONTENT_ADDITIONALINFO_FIELDSET_LABEL">
<field name="tagline" type="text" size="50" default="" label="PLG_CONTENT_ADDITIONALINFO_TAGLINE_LABEL" description="PLG_CONTENT_ADDITIONALINFO_TAGLINE_DESC" />
<field name="pseudocategory" type="category" extension="com_content" label="PLG_CONTENT_ADDITIONALINFO_PSEUDOCATEGORY_FIELD_LABEL" description="PLG_CONTENT_ADDITIONALINFO_PSEUDOCATEGORY_FIELD_DESC" />
</fieldset>
</fields>
</form>
This however does not work, whenever I do something like above, the form fields never show up on the admin form (even though I have it set correctly, and the only thing that changed between the user plugin and the content plugin is the name of the form i'd like the form to appear on
When I change my XML to this:
<?xml version="1.0" encoding="utf-8"?>
<form>
<fields name="attribs">
<fieldset name="additionalinfo_fieldset" label="PLG_CONTENT_ADDITIONALINFO_FIELDSET_LABEL">
<field name="tagline" type="text" size="50" default="" label="PLG_CONTENT_ADDITIONALINFO_TAGLINE_LABEL" description="PLG_CONTENT_ADDITIONALINFO_TAGLINE_DESC" />
<field name="pseudocategory" type="category" extension="com_content" label="PLG_CONTENT_ADDITIONALINFO_PSEUDOCATEGORY_FIELD_LABEL" description="PLG_CONTENT_ADDITIONALINFO_PSEUDOCATEGORY_FIELD_DESC" />
</fieldset>
</fields>
</form>
When I make this simple change, the form fields show up! BUT, the data isn't stored or retrieved from the custom table, it just goes into the 'attribs' column on the _content table. This stores the content in JSON, which is alright, but we'd like to be able to index the content by the custom fields (and not have to loop through each record in the database to find what we're looking for).
Any ideas on how to fix this?
thanks!
david barratt
I guess your plugin file ( for example, "yourplugin.php" ) will have one method called "onContentPrepareForm". If you want to add data to an article, this method should start like this:
function onContentPrepareForm($form, $data)
{
if (!($form instanceof JForm))
{
$this->_subject->setError('JERROR_NOT_A_FORM');
return false;
}
// Check we're manipulating an
if ( $form->getName() != "com_content.article" ) {
return true;
}
//[...] The rest of your code here
Besides, if you want to store these fields in another table in order to make it easier to search using this fields, maybe you should create a new table and save the data using the "onContentAfterSave" method:
public function onContentAfterSave( $context, &$article, $isNew )
On this method, you should always check that $context is "com_content.article", otherwise you might face problems when saving categories.
I hope it helps!
I have an employee entity in my EF model. I then added a class to the project to add a custom property
public partial class Employee
{
public string Name
{
get { return string.Format("{0} {1}", this.FirstName, this.LastName); }
}
}
On a aspx form (inside a FormView), I want to bind a DropDownList to the employee collection:
<asp:Label runat="server" AssociatedControlID="ddlManagerId"
Text="ManagerId" />
<asp:DropDownList ID="ddlManagerId" runat="server"
DataSourceID="edsManagerId"
DataValueField="Id"
DataTextField="Name"
AppendDataBoundItems="true"
SelectedValue='<%# Bind("ManagerId") %>'>
<asp:ListItem Text="-- Select --" Value="0" />
</asp:DropDownList>
<asp:EntityDataSource ID="edsManagerId" runat="server"
ConnectionString="name=Entities"
DefaultContainerName="Entities"
EntitySetName="Employees"
EntityTypeFilter="Employee"
EnableFlattening="true">
</asp:EntityDataSource>
Unfortunately, when I fire up the page, I get an error:
DataBinding: 'System.Web.UI.WebControls.EntityDataSourceWrapper' does not contain a property with the name 'Name'.
Any ideas what I'm doing wrong?
After much searching I discovered that that the EntityDataSource does not support custom properties in the partial classes. It only returns the entity that is in the model.
As per this article:
The issue is that we’re using the EntityDataSourceWrapper and not our actual entity. The solution? Stop using the wrapper!
Disable flattening, like this:
<asp:EntityDataSource
...
EnableFlattening="False"
...
</asp:EntityDataSource>
More information on Flattening is here.
Could you verify that both your partial Employee classes are in the same namespace?