TYPO3 7.6 - is there any way to Override TYPES? - typo3-7.6.x

I am using user defined render types to add HTML Code or funktionlity to Dropdowns, ets. But can I also override text fields?
Example:
$GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeRegistry'][1476278844] = [
'nodeName' => 'myNewSelect',
'priority' => 40,
'class' => \WFP2\MyExt\Form\Element\NewSelectElement::class,
];
In this class I derive from SelectMultipleSideBySideElement and now I can use the render method and Change the return of it.
But How to do this on other fields, which do not have a render type?
regards
n00n

Related

Nesting content from template in HAML tag from partial

Problem
I have a partial, which contains HTML structure for repeating elements of FAQ entry.
partials/_faqitem.haml:
.question
%a.faq-toggle{"data-toggle" => "collapse", :href => "\##{item}"}
= data.faq[item].q
%div{:class => "collapse", :id => "#{item}"}
Text directly in partial
I am using it in my faq.html.md.erb.haml template:
= partial(:"partials/faqitem", :locals => { :item => "so" })
This properly renders HTML and inserts data from data/faq.yaml:
so:
q: What is Stack Overflow?
info: Some other info
The problem arises when I try to add more text back in my template, under = partial call. I can't nail proper indentation that would allow me to render text in template inside div tag, in the same way as "Text directly in partial" is rendered.
Example of nesting in the template:
= partial(:"partials/faqitem", :locals => { :item => "so" })
Text in the template
= partial(:"partials/faqitem", :locals => { :item => "so" })
Text in the template
Depending on the level of nesting, I get either one of these errors:
syntax error, unexpected keyword_end, expecting end-of-input y in partial\n", 0, false);end;_hamlout.buffer << _hamlout.f ^
or
The line was indented 2 levels deeper than the previous line.
Is there any way to add text directly in the template in a way that will be rendered in the same way as if it would be nested inside tag from the partial?
Specific example
To better illustrate desired result, here is an example.
faq.html.md.erb.haml template:
= partial(:"partials/faqitem", :locals => { :item => "so" })
This is some text in the template.
:markdown
Now a *little* markdown to complicate things and then I will insert some information from data file, because I don't want to repeat myself.
= data.faq.so.info
This, used with partials/_faqitem.haml:
.question
%a.faq-toggle{"data-toggle" => "collapse", :href => "\##{item}"}
= spanmarkdown(data.faq[item].q)
%div{:class => "collapse", :id => "#{item}"
Should produce the same result as if the content from template was placed directly inside partial:
.question
%a.faq-toggle{"data-toggle" => "collapse", :href => "\##{item}"}
= spanmarkdown(data.faq[item].q)
%div{:class => "collapse", :id => "#{item}"}
This is some text in the template.
:markdown
Now a *little* markdown to complicate things and then I will insert some information from data file, because I don't want to repeat myself.
= data.faq.so.info
I am not sure about this syntax, I always use render to render my partial and indentation works just fine. Why not just do this:
= render "partials/faqitem", item: "so"
%div
Text in the template

Model binding fails with Kendo MultiSelect

In the model I have long? field that I like to use Kendo MultiSelect for it. The main reason for this choice is server-side filtering. It doesn't reflect current Model's value, nor it sends any value to the server. By inspected traffic, I'm sure that it doesn't update the model's value.
#(Html.Kendo().MultiSelectFor(x => x.theField)
.Name("msname")
.MaxSelectedItems(1)
.Placeholder("")
.HighlightFirst(true)
.DataValueField("Id")
.DataTextField("Text")
.AutoBind(true)
.DataSource(ds =>
ds.Read(" ", "API").ServerFiltering(true))
.Value(new long?[] { Model.theField})
)
I can put a hidden field and update its value or multiselect's change, but there should be a better solution.
I should note that this multi select is in an editor template and is used by Kendo Grid in popup editor.
UPDATE
When using nullable types, you need to use ValuePrimitive(true)! So the end code is:
#(Html.Kendo().MultiSelectFor(x => x.theField)
.MaxSelectedItems(1)
.Placeholder("")
.HighlightFirst(true)
.DataValueField("Id")
.DataTextField("Text")
.AutoBind(true)
.DataSource(ds =>
ds.Read(" ", "API").ServerFiltering(true))
.ValuePrimitive(true)
)
The main reason for this choice is server-side filtering
You can find on their demo site that DropDownList and ComboBox also support that feature. But if you insist to use MultiSelect then lets dig some of your code.
Look Name() method will give a name for your input element e.g (input, select). When form serialized it will use our input name as form's field property. If you are using HtmlHelper that ends with "For" e.g (LabelFor, MultiSelectFor) input attribute name will be named by its binded property.
Html.Kendo().MultiSelectFor(x => x.theField)
You will have
<select name="theField"> ....
You don't have to use Name() method anymore, therefore MultiSelect value will be binded as theField property as per form serialized to server.
Now if you look to Request.Form["theField"] when you debug inside your controller, you will see what value being sent. It usually a content of joined string array if multiple items selected, so you need to change theField type to handle array of string or int instead of nullable long type.
EDIT
At last you find the way to solve your problem, this solution credit to Akbari
When using nullable types, you need to use .ValuePrimitive(true)

Kendo Grid filtering with an enumeration

My model contains an enumeration that I'd like to filter the grid on when it's loaded via AJAX.
.cshtml Code:
#(Html.Kendo().Grid()
.Name("Grid")
.Columns(columns =>
{
columns.Bound(x => x.Type);
columns.Bound(x => x.Status); #*This is my enum*#
})
.Filterable()
.DataSource(ds => ds
.Ajax()
.ServerOperation(true)
.Filter(filter => filter.Add(x => x.Status).IsEqualTo(MyEnum.Updated))
.Read(read => read.Action("QueryAlerts", "Alert"))))
The filter request on the AJAX POST is going across as Status~eq~'updated' and returns an Input string was not in a correct format error.
I removed the filtering on the data source and used the filtering controls to see how that request is normally passed which looks like this: Status~eq~2.
I've tried casting the filter values to integers (e.g. filter.Add(x => (int)x.Status).IsEqualTo((int)MyEnum.Updated)) and that results in an invalid cast error to Int32 from the model which is expected by the Add method.
Can this problem be solved using Razor or is this a JavaScript fix?
What data type is your x.Status? If it's an int then you don't need to cast it, only the enumeration:
filter.Add(x => x.Status).IsEqualTo((int)MyEnum.Updated)

Kendo UI with ASP.NET MVC3 default values when adding row to grid

I am converting an existing app from Telerik MVC extensions to the newer KendoUI product. I am using the grid control. How do I specify the default values for the columns when adding a new row to the grid?
With the old Telerik MVC extensions, I did the following:
.Editable(editing=>editing.Mode(GridEditMode.InCell).DefaultDataItem(Model.defaultItem))
The defaultItem of my model was my default for added rows. So how do I do this with Kendo?
Yo yo yo mate,
You need to specify default value for each of the fields via the dataSource model configuration
Here is an example you can use ;)
#(Html.Kendo()
.Grid<TestModel>()
.Name("SomeOtherGridName")
.DataSource(ds => ds.Ajax().Read("test", "test").Model(
x => {
x.Field(c => c.Val1).DefaultValue(5);
x.Field(c => c.Val2).DefaultValue("cool!");
}
))
.Columns(columns =>
{
columns.Bound(c => c.Val1);
columns.Bound(c => c.Val2);
})
)
DefaultDataItem does not currently exist in the MVC extensions specifically. However, it is still possible without using the MVC extensions as a work-around.
I wrote an extension method that accomplishes the core functionality of DefaultDataItem(). It reads every property of a default item and sets the Field() and DefaultValue() in the data source model definition:
public static class DataSourceModelDescriptorFactoryExtensions
{
public static DataSourceModelDescriptorFactory<TModel> DefaultDataItem<TModel>(
this DataSourceModelDescriptorFactory<TModel> dataSourceModelBuilder,
TModel defaultDataItem) where TModel : class
{
var propertyInfos = typeof(TModel).GetProperties();
foreach (var propertyInfo in propertyInfos)
{
dataSourceModelBuilder
.Field(propertyInfo.Name, propertyInfo.PropertyType)
.DefaultValue(propertyInfo.GetValue(defaultDataItem));
}
return dataSourceModelBuilder;
}
}
Use it like this:
#(Html.Kendo().Grid<MyEntity>()
...
.DataSource(ds => ds
...
.Model(model =>
{
model.Id(n => n.Id);
model.DefaultDataItem(myDefaultEntity);
}
)
)

ASP.NET MVC 3 Data Attributes - Programmatically Set UIHint from Controller

If i have a ViewModel like this:
public class SignupViewModel
{
[Required]
[DisplayName("Email:")]
public string EmailAddress { get; set; }
}
And use EditorFor to render out the form fields:
#Html.EditorFor(model => model.EmailAddress )
It will render <input type="text">. Cool.
But in this particular scenario, i have already retrieved Email from a different source, and i wish to pre-fill the form with this data, and show a label instead of a textbox (as i don't want them to change their email - don't worry about why).
I know i can use [UIHint], but can i do that programatically from the controller?
E.g:
var model = new SignupViewModel();
model.EmailAddress = GetFromMysterySource(); // How do i set a UIHint?
What's the best way to approach this? Should i use a seperate ViewModel altogether, which could mean changing my View from being strongly-typed to being dynamic, or should i not use EditorFor, or should i use a custom editor template?
Suggestions/advise would be greatly appreciated.
You can't apply an attribute at runtime. My suggestion would be to build a bit of logic into your view to control how the view renders the data. You may need to augment your model to indicate to the view which display to choose.
#if (Model.EmailAddressIsFixed)
{
#Html.DisplayFor( m => m.EmailAddress )
#Html.HiddenFor( m => m.EmailAddress ) // only if you need it to post back
}
else
{
#Html.EditorFor( m => m.EmailAddress )
}
If you are doing this in more than one place, then a custom editor template doing the same thing would probably be in order.
#Html.EditorFor( m => m.EmailAddress,
"FixedAddressTemplate",
new { Fixed = Model.EmailAddressIsFixed } )

Resources