Joomla 3 custom field get xml field - joomla3.0

I am creating a custom field to create an array of input images as media type.
How can I bring back the input array with type media?
class JFormFieldimglist extends JFormField {
//The field class must know its own type through the variable $type.
protected $type = 'imglist';
public function getLabel() {
return "List Image";
}
public function getInput() {
for ($i = 1; $i <= 10; $i++) {
$images.= '<input type="text" value="'.$this->value[$i].'" name="'.$this->name.'['.$i.']" />';
}
return $images;
}
}
From xml i use this
<field name = "myimage" type = "media" directory = "stories" />

There are two issues. The first issue is your extending the core JFormField class. The second issue is the media field type is actually a modal form field. This is a special kind of field which is used to present a more complicated interface in a modal window for the user to select. Examples of this are when you select an Article for a Menu Type Single Article, or click the Image button located underneath the WYSIWYG editors.
My guess is you want to pull in a list of images from a specific folder for the user to select from a drop down. In the example below notice I have completely omitted the getLabel() and getInput() methods and added getOptions(). The reason being is by extending the JFormFieldList class those methods are already built out and outside of special requirements are not needed. You simply override the getOptions() method to provide the core class the list of option you want to be presented in the field.
jimport('joomla.form.helper');
JFormHelper::loadFieldClass('list');
class JFormFieldimglist extends JFormFieldList {
//The field class must know its own type through the variable $type.
protected $type = 'imglist';
public function getOptions() {
// build out your options array
// You should format as array, with full path as key and
// human readable as value
$options = array('/images/flowers/tulip.png' => 'Tulip');
return $options;
}
}
Here are some links for expand on my post.
http://docs.joomla.org/Creating_a_custom_form_field_type
http://docs.joomla.org/List_form_field_type
http://docs.joomla.org/Creating_a_modal_form_field

Related

How to show computed property values in EPiServer 8?

In page edit mode I want to show a read-only text that is based on a page property value. The text could for example be "A content review reminder email will be sent 2015-10-10", where the date is based on the page published date + six months (a value that will be configurable and therefore can change anytime). So far I've tried to accomplish something like this by adding another property on the page.
I've added the property CurrentReviewReminderDate to an InformationPage class we use. In page edit mode the property name is shown, but it doesn't have a value. How do I do to show the value in page edit mode (preferably as a label)?
[CultureSpecific]
[Display(
Name = "Review reminder date",
Description = "On this date a reminder will be sent to the selected mail to remember to verify page content",
Order = 110)]
[Editable(false)]
public virtual string CurrentReviewReminderDate
{
get
{
var daysUntilFirstLevelReminder =
int.Parse(WebConfigurationManager.AppSettings["PageReviewReminder_DaysUntilFirstLevelReminder"]);
if (CheckPublishedStatus(PagePublishedStatus.Published))
{
return StartPublish.AddDays(daysUntilFirstLevelReminder).ToString();
}
return "";
}
set
{
this.SetPropertyValue(p => p.CurrentReviewReminderDate, value);
}
}
EPiServer internally uses the GetPropertyValue method (i.e. the opposite of SetPropertyValue) when retrieving content for the UI.
This makes sense, otherwise your "made-up" value would be stored as the real value whenever the content is saved. This would make fall-back values etc impossible to implement.
So, this is by-design (and quite wisely so) in EPiServer. :)
However, you can customize how properties work by:
Using custom editors by applying UI hints
Modifying property metadata (for example, to display a generated value as a watermark in a textbox without interfering with the actual value being saved)
I could be misunderstanding what you're trying to do, but off the top of my head it looks like a custom editor could be a viable option for your use case?
Another solution would be to hook into the LoadedPage-event and add the value from there. This might not be the best way performance-wise since you need to do a CreateWritableClone, but depending on the site it might not matter.
[InitializableModule]
[ModuleDependency(typeof(EPiServer.Web.InitializationModule))]
public class EventInitialization : IInitializableModule
{
public void Initialize(InitializationEngine context)
{
ServiceLocator.Current.GetInstance<IContentEvents>().LoadedContent += eventRegistry_LoadedContent;
}
void eventRegistry_LoadedContent(object sender, ContentEventArgs e)
{
var p = e.Content as EventPage;
if (p != null)
{
p = p.CreateWritableClone() as EventPage;
p.EventDate = p.StartPublish.AddDays(10);
e.Content = p;
}
}
}

Yii2 add condition in the last one of chain relations

Right now I have:
$products = Product::findAll([1,2,3,4]);
foreach ($products as $product){
$text = $product->part->type->texts;
}
This returns the related records from Texts table.
But I need to have only 1 record from it, and to do that I need to have one more condition in the last join type->texts, which is not defined in the model. It's dynamic session variable.
Is there any way to do this?
If you want modify the last relation query to have additional condition and return one record instead of many, simply change last relation call like so:
$text = $product->part->type->getTexts()->andWhere(...)->one();
Direct relation method call returns yii\db\ActiveQuery instance so you can modify conditions how you want.
If you want to use modified relation in more than just one place, create separate method for that:
/**
* #return yii\db\ActiveQuery
*/
public function getDynamicText()
{
// Insert link from texts relation similar as in hasMany() and additional condition in andWhere()
return $this->hasOne(...)->andWhere(...);
}
And then use it:
$text = $product->part->type->dynamicText;
In this case, scopes would be a handy solution, especially if you're going to use complicated conditions.
1. Start by creating a model that extends ActiveQuery with a method that will be used to add conditions to your query, for example active = 1:
namespace app\models;
use yii\db\ActiveQuery;
class TextQuery extends ActiveQuery
{
public function active($state = 1)
{
$this->andWhere(['active' => $state]); // or any other condition
return $this;
}
}
2. Override the find() method in your Text model:
public static function find()
{
return new \app\models\TextQuery(get_called_class());
}
3. Add a method in your Type model that retrieves your relational data via the newly made scope:
public function getActiveText()
{
return $this->hasMany(Text::className(), ['type_id' => 'id'])->active();
}
Finally, use it as follows:
$text = $product->part->type->activeText;
The docs are pretty clear on this, check 'em out.

Symfony2 array of custom objects into form fields

I get some data from an API inside my Symfony 2 application using Guzzle. Those data are properly mapped into my model. The model is a Contact object with some properties. One of those property is an array of ContactMethod done like this
/**
* #SerializedName("methods")
* #Type("array<My\Bundle\Model\ContactMethod>")
*/
private $methods;
The ContactMethod object has just two properties: type and value
class ContactMethod {
/**
* #SerializedName("type")
* #Type("string")
*/
private $type;
/**
* #SerializedName("value")
* #Type("string")
*/
private $value;
... setters and getters ...
I've created a ContactType with its buildForm function in order to display all the property of Contact in a form. But when it comes to display the methods property I would like to have a TextInput for each of the ContactMethod and that input should take the type as label and the value as value.
class ContactType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options = array())
{
$builder
->add(...all the other simple fields...)
->add(...what shall I add here ? )
I also need this to work in the opposite way: when all the text inputs are filled and submitted, the fields has to be packed together into an array of ContactMethod so I can reserialize and send back the data to the API.
I've tried to play around with custom form types and also Data Transformers but I could not find a solution.
Your Contact object is mapped onto one ContactType, so just add a property methods and its type (e.g.) "method_list" if it's declared as a service or just new MethodListType().
The list is dynamic, so you have to write your own buildView method for the new Type.

Localization in MEF: export attribute does not support a resource (WPF - C#)

I have an application with a plugin architecture using MEF. For every exported part there is an attribute with the part's name, and I want to have the names translated, because I use these strings to display the available parts in ListBoxes (or the like).
So, I tried to set the 'Name = Strings.SomeText" in the [Export] annotation, but I get the following error:
"An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type"
Is there a solution to this? I find the use of the Metadata very useful (I do lazy loading) and I would not want to redesign everything just to get a few texts translated.
Any ideas? Thanks.
Unfortunately you can't directly provide the translated text to the attributes because an attribute can only contain data that is known at compile time. So you will need to provide some compile time constant value that you can later use to look up the translated test.
One solution would be to pass the resource name to the attribute. Then when you want to display the translated text you grab the resource name, look up the text in the resources and display the result.
For instance your attribute could look something like:
[Export(Name = "SomeText")]
public class MyExport
{
}
Then when you want to display the string you load the resources from the assembly that defines the export and you extract the actual text from the loaded resources. For instance like this (as borrowed from another answer):
var assembly = typeof(MyExport).Assembly;
// Resource file.. namespace.ClassName
var rm = new ResourceManager("MyAssembly.Strings", assembly);
// exportName contains the text provided to the Name property
// of the Export attribute
var text = rm.GetString(exportName);
The one obvious drawback about this solution is that you lose the type-safety that you get from using the Strings.SomeText property.
--------- EDIT ---------
In order to make it a little easier to get the translated text you could create a derivative of the ExportAttribute which takes enough information to extract the translated text. For example the custom ExportAttribute could look like this
public sealed class NamedExportAttribute : ExportAttribute
{
public NamedExportAttribute()
: base()
{
}
public string ResourceName
{
get;
set;
}
public Type ResourceType
{
get;
set;
}
public string ResourceText()
{
var rm = new ResourceManager(ResourceType);
return rm.GetString(ResourceName);
}
}
Using this attribute you can apply it like this
[NamedExport(
ResourceName = "SomeText",
ResourceType = typeof(MyNamespace.Properties.Resources))]
public sealed class MyClass
{
}
Finally when you need to get the translated text you can do this
var attribute = typeof(MyClass).GetCustomAttribute<NamedExportAttribute>();
var text = attribute.ResourceText();
Another option is to use the DisplayAttribute

Sorting a CellTable server-side

I'm currently using a Gwt CellTable, bound to my GAE/Objectify backend via RPC calls.
All right now! :-)
Then I want to sort columns, so I read http://code.google.com/intl/it-IT/webtoolkit/doc/latest/DevGuideUiCellTable.html#columnSorting
The Async Remote sorting sections shows very well how to get sorting into my AsyncDataProvider but... how can I retrieve the name of the column the user wants to sort?
It shows this code: ColumnSortList sortList = table.getColumnSortList();
But how can I get String names from that? I simply want to know "surname" or "soldDate", the name of the field the column is bound to! Then I will pass it to my rpc service, and use it to sort data server-side query(...).order(<field_name>)
Am I missing something?
UPD: interesting stuff here: http://groups.google.com/group/google-web-toolkit/browse_thread/thread/77a0eaf8086218a6/effb8d3abe69270b#effb8d3abe69270b
You can keep a list of column names ordered as they are in the table:
List<String> columnNames = new ArrayList<String>();
table.addColumn(surnameColumn, "surname");
columnNames.add("surname");
// add the other columns
Then when you need to get the sort column name:
String sortColumnName;
ColumnSortList sortList = table.getColumnSortList();
if (sortList != null && sortList.size() != 0){
Column <MyEntity, ?> sortColumn = (Column <MyEntity, ?>)
sortList.get(0).getColumn();
Integer columnIndex = table.getColumnIndex(sortColumn);
sortColumnName = columnNames.get(columnIndex);
}
// do your rpc call
*where MyEntity is your data object displayed in the cell table.
A bit late to the party, but here's a more straight-forward solution based off of the current documentation (see section 'ColumnSorting with AsyncDataProvider').
When we're adding our columns we can simply set the dataStoreName:
TextColumn<MyData> surname = new TextColumn<MyData>() {
...
}
surname.setSortable(true);
surname.setDataStoreName("surname"); // Set the column name
table.getColumnSortList().push(surname);
table.addColumn(surname, "Last Name"); // eg. A different name for the UI
Then we can retrieve the column's dataStoreName later when sorting:
#Override
protected void onRangedChanged(HasData<MyData> display) {
...
ColumnSortList.ColumnSortInfo info = table.getColumnSortList().get(0);
String sortColumn = info.getColumn().getDataStoreName(); // Get the column name
boolean sortIsAscending = info.isAscending();
rpcService.requestMyData(
sortColumn,
sortIsAscending,
new AsyncCallback<ArrayList<MyData>>() {...}
);
...
}
Using this method we can pass the column name directly to our RPC method. It even allows us to use a different name (eg. the database column name) than the column name used on the UI/client side.
I have used something like this as an application column object.
public class ScrollTableColumn
{
// --------------------------------------------------------------- Field(s)
private int sequence;
private Column column;
private Header header;
private int size;
private int calculatedSize;
private boolean show;
private PartialColumn partialColumn;
private ColumnNameEnum columnName;
}
Now create a HashMap of the above as follows:
Map<Column, ScrollTableColumn> columnMap
= new HashMap<Column, ScrollTableColumn>();
Add all the columns as you create them both in the ScrollTableColumn and in the columnMap.
Finally you can get the required name as:
ColumnSortList sortList = dataTable.getColumnSortList();
Column<?, ?> column = sortList.get(0).getColumn();
ColumnNameEnum = columnMap.get(column);
String name = ColumnNameEnum.getName();
The proper way is to extend the base column class which will allow you to override cell rendering, pass in column configuration via your constructor, and most importantly set the DataStoreName which is where you should store the field name for the column. Lastly you should not reuse the onrangechanged fire, but access the columnsort handler directly by overriding it. on range change and column sort handler should call some type of method that you have to update your grid. I call mine updateGrid for sanity. This allows you to set any grid parameters used by your async request to specific sort column and direction. The main reason you want to use column sort handler is to access the ColumnSort event which contains your sort direction information
your column class that extends the base GWT column. You can also extend date or number columns too.
public GridStringColumn(String fieldName, String text, String tooltip, boolean defaultShown, boolean sortable, boolean hidden) {
super(new TextCell());
setDataStoreName(fieldName);
this.text_ = text;
this.tooltip_ = tooltip;
this.defaultShown_ = defaultShown;
setSortable(sortable);
this.hidden_ = hidden;
}
create your handler
dataGrid.addColumnSortHandler(new DataGridSortEvent());
your sort event class
protected class DataGridSortEvent implements ColumnSortEvent.Handler {
#Override
public void onColumnSort(ColumnSortEvent event) {
ColumnSortList sortList = dataGrid_.getColumnSortList();
if (sortList != null && sortList.size() > 0) {
Column<T, ?> sortColumn = (Column<T, ?>) sortList.get(0).getColumn();
LOG.info("col_sorta: " + event.isSortAscending());
LOG.info("col_index: " + sortColumn.getDataStoreName());
updateDataList();
}
}
}
updateDataList is your method you use to make the actual AJAX request to your server side. rather then logging you sould store this info in private members of your datagrid class so that your request can parameterize them.
you could also make this work for local caching too, just make a copy of the data from your server locally then return a sorted collection of that cached collection, rather then calling the updateDataList method.
Now you do not need to store a separate list for just string names, which is waste of memory not to mention a synchronicity issue if the column order is change from user interaction or whatever.

Resources