Using the link wizard in a Typo3 backend module - extbase

I'm pulling my hair out over this.
I created a T3-Extension - backend module - using Extension Builder.
Now I want to provide the user with the link-wizard, so she/he can select an internal link from the T3-Tree.
I created a TCA-Entry for this:
'url' => [
'label' => 'Link',
'exclude' => 1,
'config' => [
'type' => 'input',
'size' => '50',
'max' => '256',
'eval' => 'trim',
'renderType' => 'inputLink',
'fieldControl' => [
'linkPopup' => [
'options' => [
'blinkLinkOptions' => 'mail,page,spec,url,folder',
'blindLinkFields' => 'class,params,target,title',
'allowedExtensions' => 'html,php'
],
],
],
'fieldWizard' => [
'localizationStateSelector' => [
'disabled' => false,
]
]
],
],
In the fluid-template (the view) I'm simply using this:
<f:form.textfield property="url" />
According to the docs, the TCA-config should add a button after the input field.
But that's not the case.
Am I doing something wrong or is this simply not working?
I also tried using flux in my templates (which has a link-browser view helper), but when I use <flux:...> nothing is rendered in the form.
Using Typo3 8.7

I finally found a solution for this.
This is in the controller of my extension
$options = [
'renderType' => 'inputLink',
'tableName' => 'myTable',
'fieldName' => 'url',
'databaseRow' => [
'uid' => $myModel->getUid(),
'pid' => 0
],
'parameterArray' => [
'fieldConf' => [
'label' => 'URL',
'config' => [
'eval' => 'trim',
'size' => 1024,
],
],
'itemFormElValue' => $myModel->getUrl(),
'itemFormElName' => 'data[myTable][editform][url]',
'itemFormElID' => 'data[mytable][editform][url]',
'field' => 'url',
'fieldChangeFunc' => [
'TBE_EDITOR_fieldChanged' => "TBE_EDITOR.fieldChanged('mytable','editform','url','data[mytable][editform][url]');"
],
]
];
$nodeFactory = new NodeFactory();
$linkField = new InputLinkElement($nodeFactory, $options);
$urlField = $linkField->render();
$this->view->assign('renderedUrlField', $urlField['html']);
Where «mytable» is the table the controller uses, «editform» is the form-name and «url» is the database-field that's been used to store the value.
For some reason, you need to name your form «editform», since a sysext-JS refers to that.
You need to add this to your controller to make this working:
use TYPO3\CMS\Backend\Form\Element\InputLinkElement;
use TYPO3\CMS\Backend\Form\NodeFactory;
And in the fluid-template, you have to use:
<f:format.raw>{renderedUrlField}</f:format.raw>
because it returns html-code.
Now initialize the FormEngine
Add this to your Default.html in the section <f:be.container...>:
includeJsFiles="{
1:'/typo3/sysext/backend/Resources/Public/JavaScript/jsfunc.tbe_editor.js',
3:'/typo3/sysext/backend/Resources/Public/JavaScript/jsfunc.inline.js',
4:'/typo3/sysext/backend/Resources/Public/JavaScript/backend.js'
}"
includeRequireJsModules="{
0:'{f:uri.resource(path:\'JavaScript/ckeditor/ckeditor.js\')}',
4:'TYPO3/CMS/Backend/FormEngine',
5:'TYPO3/CMS/Backend/FormEngineValidation',
7:'TYPO3/CMS/Backend/ContextMenu',
8:'TYPO3/CMS/Backend/FormEngineReview',
9:'{f:uri.resource(path:\'JavaScript/main.js\')}'
}"
I included ckeditor as well here.
And now, you need to initialize the FormEngine. I did this in main.js:
TYPO3.settings.FormEngine = {"formName":"editform"};
define(['jquery', 'TYPO3/CMS/Backend/FormEngine'], function($){
'use strict';
$(function(){
TYPO3.FormEngine.initialize();
});
});
The first line is important, otherwise, the JS will throw an error.
Hope this helps somebody.

My answer will not help if you want to create the link wizard with Fluid, but it answers a part of the question and adds additional information.
Setting the link wizard for a field via TCA will not magically make the link wizard appear in Fluid. It will however make the link wizard available if you directly edit a record in the backend (with the list view).
Example: you create a table tx_myext_domain_model_mydata with the field url, set the TCA to use the link wizard. Then use the list view to create and edit records.
You can see examples of records with a link wizard in the extension styleguide. It is good to use this extension, because it is a semi-official demo of various backend functionality. The extension "news" for example also makes use of editing news records (tx_news_domain_model_news.internalurl).
Install "styleguide" extension, create sample records, select "elements basic" and look at for example "input_29 link" (for TYPO3 8). See source code and TCA Reference renderType inputLink.

Related

drupal 8 conditional field with link field

I am trying to work a conditional field based on the value input in a link field. For example, based on an external or internal link. I couldn't find a proper example, but the ones I found, I have tried this, no luck. Any idea how this can work -
$form['field_test_1']['#states'] = [
'visible' => [
':input[name="field_test_2[widget][0][uri][#default_value]"]' => 'https://www.google.com',
],
];
ok so I have worked it out, it should be like this -
$form['field_test_1']['#states'] = [
'visible' => [
':input[name="field_test_2[0][uri]"]' => [ 'value' => 'https://www.google.com' ],
],
];

CKEditor Plugin 'save' (egeloen / ivoryckeditor) in Symfony 3 not showing the save button

I successfully installed and integrated the CKEditor (4.7.3) in my Symfony 3.3.10 project using the ckeditor-bundle from egeloen (ivoryckeditor).
I am now trying to get the "Save" Plugin to work.
I copied the plugin folder into my web-folder.
This is my test configuration in config.yml
ivory_ck_editor:
inline: true
autoload: false
async: false
configs:
ckeditor_config_1:
toolbar: [ [ "Save", "Cut", "Copy" ] ]
extraPlugins: "save"
plugins:
save:
path: "/bundles/ivoryckeditor/plugins/save/"
filename: "plugin.js"
Thats how I create the ckeditor form to pass to twig for rendering:
$ckeditForm = $this->get('form.factory')->createNamedBuilder('ckedit_form', CKEditorType::class, $content, array(
'label' => false,
'config' => array(
'config_name' => 'ckeditor_config_1',
'inline' => true,
),
))->getForm();
Unfortunately the "Save" Button is not showing up.
Any ideas about the cause of the button not showing up are very welcome.
OK - The save plugin is just not working in inline mode. Could be documented somewhere - couldn't find any hint to that...

CollectionType element validation error message location

I'm working with a CollectionType field.
$builder->add('urls', CollectionType::class, [
'allow_add'=>true,
'entry_type'=>UrlType::class,
'constraints'=>new All([
'constraints'=>[
new Url()
]
])
]);
It works as I expected. Except the message if field has an invalid content.
Validator works but error message is a bit confusing: Field.0 - This value is not a valid URL address. What do I need is to simply make a parent field invalid - bind error to urls field.
Of course, I could create a form listener and perform validation there. But - IMO - it's a workaround.
How to achieve this in a "pure" way? I've tried playing error_bubbling in many ways but it's still not something satisfying.
try, so you for force validation on each UrlType and have it bubble the error upwards to the parent form, the CollectionType
$builder->add('urls', CollectionType::class, [
'allow_add'=>true,
'entry_type'=>UrlType::class,
'constraints'=>new All([
'constraints'=>[
new Url()
]
]),
'cascade_validation' => true,
'entry_options' => array('error_bubbling' => true)
]);
I think that you need to set error_mapping:
$builder->add('urls', CollectionType::class, [
'allow_add'=>true,
'entry_type'=>UrlType::class,
'constraints'=>new All([
'constraints'=>[
new Url()
]
]),
'cascade_validation' => true,
'error_bubbling' => false,
'error_mapping' => [
'your_parent_form_alias.field_name' => 'field_name',
]
]);
and then in UrlValidator when you are building violation add atPath like that:
if (empty($form['field_name'])) {
$this->context->buildViolation($constraint->getMessageName())
->atPath('your_parent_form_alias.field_name')
->addViolation();
}
I'm not sure does error_mapping and error_bubbling shouldn't be mapped first for Url() and later one more time for All().
I hope it will help you

In DjangoCMS Can I have an HTMLField which has use of the cmsplugins?

I'm buidling a site with DjangoCMS 3.1, using a mix of traditional Django Models with fields and DjangoCMS placeholders. This is fine in principal, but it doesn't really allow for a clean workflow for the site administrators as they have to edit half of a model in the more traditional admin interface, and then the placeholder via the front-end editor interface. As I don't really need the full front-end-editing interface to simplify things such I wanted to convert all of the fields defined as PlaceHolderField's into HTMLFields.
Having done this I am having problems accessing the CMSplugins from within CKEditor in the admin interface; the appropriate button shows up in CKEditor, but the drop down menu is empty:
This is my (simplified) model description:
class Project(models.Model):
start_date = models.DateField('Start Date', blank=True, null=True)
end_date = models.DateField('End Date', blank=True, null=True)
subtitle = models.CharField('Sub Title', max_length=512, blank=True, null=True)
contents = HTMLField('Contents')
Admin declaration:
class ProjectAdmin(FrontendEditableAdminMixin, reversion.VersionAdmin):
fieldsets = [
(None,
{'fields':
[
'title',
'type',
'start_date',
'end_date',
'subtitle',
'summary',
'contents',
]
}
),
('Meta Information',{
'classes': ('collapse',),
'fields':
[
'slug',
'legacy_id',
'created_date',
'modified_date',
],
}
)
]
frontend_editable_fields = (
'title',
'start_date',
'end_date',
'lead_image',
'subtitle',
'summary',
'contents'
)
Settings.py
CKEDITOR_SETTINGS = {
'language': '{{ language }}',
'toolbar_HTMLField': [
['Undo', 'Redo'],
['cmsplugins', '-', 'ShowBlocks'],
['Format', 'Styles'],
['TextColor', 'BGColor', '-', 'PasteText', 'PasteFromWord'],
['Maximize', ''],
'/',
['Bold', 'Italic', 'Underline', '-', 'Subscript', 'Superscript', '-', 'RemoveFormat'],
['NumberedList', 'BulletedList', 'Blockquote', '-', 'Table'],
['Source']
],
'skin': 'moono',
}
I've tried declaring CMS_PLACEHOLDER_CONF inside of settings.py just in case:
CMS_PLACEHOLDER_CONF = {
'contents': {
'name' : 'Contents',
'plugins': ['TextPlugin', 'PicturePlugin', 'VideoPlugin', 'LinkPlugin'],
'text_only_plugins': ['LinkPlugin'],
'default_plugins':[
{
'plugin_type':'TextPlugin',
'values':{
'body':'<p></p>'
},
},
],
'child_classes': {
'TextPlugin': ['PicturePlugin', 'VideoPlugin', 'LinkPlugin'],
},
'parent_classes': {
'LinkPlugin': ['TextPlugin'],
},
}
}
Looking at the source that shouldn't affect it, only the definition of PlaceHolderFields. I've tried adding the PlaceholderAdminMixin to the admin class declaration as well.
I'm accessing the admin interface via modal dialogs launched via {% render_model project 'contents' %} so to some extent it is within the DjangoCMS context, but it's not using the full front end interface.
Is this even possible? That is can I access the DjangoCMS Plugins via CKEditor in the Django Admin interface, without reverting to using the PlaceholderField/ full Front end editing interface?
The supported way to do this is to use PlaceholderField (where you're trying to use HTMLField.
See http://docs.django-cms.org/en/develop/how_to/placeholders.html for more information.

Wrong classes generated for batch edit

Strange thing.
My Grid seems and work correct, only untypical thing is that input during editing has:
class="text-box single-line"
instead of
class="k-textbox k-input"
Also in case when grid is completly same like in demo.
I dont know how it can happens. Copy of whole view - without some js :
#model IEnumerable<TranslationModel>
#{
ViewBag.Title = "Translations";
Layout = "~/Views/Shared/_PrivateLayout.cshtml";
Html.EnableClientValidation();
}
<h2>Translations</h2>
#(Html.Kendo().Grid<TranslationModel>(Model)
.Name("grid")
.Columns(columns =>
{
columns.Bound(e => e.Shortcut).Width(150);
columns.Bound(e => e.LanguageName).Width(100);
columns.Bound(e => e.Content);
columns.Command(command => { command.Custom("ExtraPopUpEdit").Click("ExtraPopUpEdit").Text("..."); }).Width(100);
})
.ToolBar(toolbar => {
toolbar.Save();
})
.Editable(editable => editable.Mode(GridEditMode.InCell))
.Pageable((p => p.PageSizes(new[] { 5 , 10, 20, 50, 100 })))
.Sortable()
.Filterable()
.DataSource(dataSource => dataSource
.Ajax()
.Batch(true)
.ServerOperation(true)
.PageSize(10)
.Events(events => events.Error("error_handler"))
.Aggregates(a =>
{
a.Add(e => e.Content.Equals(string.Empty)).Count();
}
)
.Model(model =>
{
model.Id(e => e.Id);
model.Field(e => e.Shortcut).Editable(false);
model.Field(e => e.LanguageName).Editable(false);
})
.Group(g => g.Add(e => e.Shortcut))
.Read(read => read.Action("Translations_Read", "Admin"))
.Update(update => update.Action("Translations_Update", "Admin"))
)
)
Those classes are rendered by ASP.NET MVC when Html.EditorFor is used. If you want to remove them you have to use editor templates.
I assume you have already figured this out on your own, but for future reference for anyone else, like me, who has this problem. The solution I found is - along the lines of what Atanas said - to just copy the EditorTemplates folder from Kendo's distribution into your project. They have templates for 12 different types (in both ascx and cshtml).
The directory I copied is within the Kendo download, in \wrappers\aspnetmvc\Examples\VS2013\Kendo.Mvc.Examples\Views\Shared\EditorTemplates. Copy that into your ~/Views/Shared, delete either the *.ascx or *.cshtml files depending on your needs, and you're good to go!

Resources