What's the easiest way to edit the default success message when saving an item in GridField edit view?
The message seems to be in a variable in class GridFieldDetailForm within method doSave.
$message = _t(
'GridFieldDetailForm.Saved',
'Saved {name} {link}',
array(
'name' => $this->record->i18n_singular_name(),
'link' => $link
)
);
Since the message uses the _t() function it will attempt to fetch the value defined in the lang file corresponding to the current user's locale. The default string defined in the function is just a fallback for when no translation could be found within the lang files.
To change the message you can update your site's yml lang file located in mysite/lang/{LANGUAGE_CODE}.yml
For english this would be:
# mysite/lang/en.yml
# remember to flush after editing me :-)
en:
GridFieldDetailForm:
Saved: 'My custom message using {name} and here is a link to the object: {link}'
https://docs.silverstripe.org/en/3.4/developer_guides/i18n/
Something like this should work for specific implementations
$form = $gridField->getConfig()->getComponentByType('GridFieldDetailForm');
$form->setItemEditFormCallback(function($form, $itemRequest)
{
// Replace save action with custom method in here
});
For more general implementations, you'll likely want to extend GridFieldDetailForm and override doSave, then replace the GridFieldDetailForm component with your custom class.
Related
I'm following the steps outlined in this documentation https://symfony.com/doc/current/controller/upload_file.html to allow a file to be uploaded. It is working perfectly for adding a new item, but when I try to edit my entity, I'm getting the following error:
The form's view data is expected to be an instance of class Symfony\Component\HttpFoundation\File\File, but is a(n) string. You can avoid this error by setting the "data_class" option to null or by adding a view transformer that transforms a(n) string to an instance of Symfony\Component\HttpFoundation\File\File.
I've tried code like what is suggested in that article to append the path of the folder as File type to the entity like this in my update method:
public function editAction(Request $request, Advertiser $advertiser)
{
$advertiser->setLogo(
new File($this->getParameter('logo_directory') .'/' . $advertiser->getLogo())
);
$editForm = $this->createForm(AdvertiserType::class, $advertiser);
$editForm->handleRequest($request);
if ($editForm->isSubmitted() && $editForm->isValid()) {
$this->getDoctrine()->getManager()->flush();
return $this->redirectToRoute('advertiser_list');
}
return $this->render('advertiser/index.html.twig', [
'form' => $editForm->createView()
]);
}
The logo_directory parameter is properly defined (and working fine for creating new entities).
Please let me know if you have any ideas what I am doing wrong.
Thanks for the help.
UPDATE: In this article The form's view data is expected to be an instance of class ... but is a(n) string there is a proposed solution to include in the form builder code the following:
->add('file', FileType::class, array('data_class' => null))
So I'm doing this now and the edit form will show - but it doesn't prepoulate with the previous selection.
->add('logo', FileType::class, array('data_class' => null), ['label' => 'Logo (JPG or PNG file)'])
Any thoughts on how this can be changed to allow the form to show with the previous selection pre-populated?
Setting a null data_class will remove the warning but it will not work, you don't need it at this point.
This is due to the fact that once your file is persisted, what remains in your database is just a path, not the file itself (which is on disk);
If you want to edit this entity again, the path (a string) must be converted to a File entity again; That's what the error message says.
.. and this is what you did when you wrote :
$advertiser->setLogo(
new File($this->getParameter('logo_directory') .'/' . $advertiser->getLogo())
);
Now, the problem that remains is that you want to prepopulate the file field. In fact, that is not possible, since the file field points to a location in your own computer, not to a file on your server (and you cannot automatically upload something from someone's computer like that, that would be very dangerous).
What you want to do is possibly indicate that a file is already stored, get its path and maybe display it to your user.
So in your Twig template, something like that (change with your real logo directory) :
{% if form.logo.vars.data %}
<img src="{{ asset('/uploads/logos_directory/' ~ form.logo.vars.data.filename) }}"/>
{% endif %}
Hope it's clear.
I have a few validation messages in the file validators.en.yml:
soporte.nombre.not_blank: The name cannot be empty
soporte.price.is_integer: The price should be integer
soporte.not_repeat: soporte cannot be repeat
I valid making a query to the database:
$validarPorNombreAndTipo = $this->crud->findOneBy(
$soporte, array('nombre' => $soporte->getNombre(),
'tipo' => $object->tipo
)
);
if ($validarPorNombreAndTipo){
$error= //here i need to get soporte.not_repeat that is on file validators.en.yml;
}
excuse me for my bad English, I used the translator.
If you just want to get the translation, this code should work :
$validarPorNombreAndTipo = $this->crud->findOneBy(
$soporte, array('nombre' => $soporte->getNombre(),
'tipo' => $object->tipo
)
);
if ($validarPorNombreAndTipo){
$error= $this->get('translator')->trans('soporte.not_repeat', array(), 'validators');
// Third param is the translation domain (first part of the translation file)
}
However, i suggest you to read this : http://symfony.com/doc/2.3/cookbook/validation/custom_constraint.html
If you want to follow Symfony best practices, you should create a custom constraint class/Validator and move your validation logic into it.
Best regards
I am trying to use a UploadField on frontend for user to upload their company logo.
There isn't much documentation on UploadField yet. And I have tried it but no luck so far.
Can anyone guide me on how to use it?
This is a little old, but if anyone else stumbles upon this like I did.
UploadField does work frontend. I haven't been able to save into a many_many relationship using the saveInto function. But the biggest thing I missed was the DataObject/Page needs to exist first, as in it needs to be saved before you can attach a related object like an image.
static $has_one = array(
"Photo" => "Image"
);
$fields = new FieldList(
new UploadField( 'Photo', 'Upload' )
);
function saveForm( $data, $form ) {
$object = new DataObject();
// for a new object write before saveinto
$object->write();
$form->saveInto($object);
$object->write();
Director::redirectBack();
}
using ss 3.0.1
Alternatively rather than using the saveinto function you can manually loop over the parameters and attach them on the object yourself for many_many images.
The upload field checks for permissions via the can*() methods in the object.
In order to allow front end editing - you may have to overload File::canEdit (or Image::canEdit) in your custom object to handle this.
I'm trying to execute some code right before content is deleted. The Rules module has events for
After updating existing content
Before saving content
After saving new content
After deleting content
However, none of these execute my code at the right time.
I discovered a simple module called Predelete, which provides hooks for executing code before deletion. This seemed like an excellent candidate to call the Rules event from.
So, I created a very simple module based on the "predelete_field" example module contained within Predelete. The folder is called "predelete_field", is in the "modules" folder, and contains the following files:
1: predelete_field.info
core = "7.x"
dependencies[] = "rules"
dependencies[] = "list"
dependencies[] = "predelete"
description = "Example for the predelete module with a content type and a node"
name = "Predelete Field"
package = Other
project = "predelete_field"
version = "7.x-1.0"
; Information added by drupal.org packaging script on 2011-07-11
version = "7.x-1.1"
core = "7.x"
project = "predelete"
datestamp = "1310360219"
2: predelete_field.module
<?php
/**
* Implements hook_predelete_node().
*/
function predelete_field_predelete_node($node) {
drupal_set_message( "PREDELETE HOOK CALLED", 'warning' );
rules_invoke_event('predelete_field', $node);
$deletable = TRUE;
$reason = t('Deletable by default.');
return array('result' => $deletable, 'reason' => $reason);
}
3: predelete_field.rules.inc
<?php
/**
* Implements hook_rules_event_info() on behalf of the predelete_field module.
*/
function rules_predelete_field_event_info() {
$items = array(
'predelete_field_predelete' => array(
'label' => t('Before deleting content'),
'group' => t('Node'),
),
);
return $items;
}
Unfortunately, this does not appear to work: The event does not show up in the event list, even after clearing cache and disabling and re-enabling the module. Likewise, the drupal_set_message function does not appear to fire.
Is anyone able to spot any errors I may have made, or provide a solution?
The Predelete module just seems to hook into the confirmation form for multiple node deletions, it won't ever be fired using Rules as Rules doesn't invoke the form but uses the node API instead.
If you look at the node_delete_multiple() function though you'll see that several hooks are called before any content is actually deleted from the database (namely hook_node_delete and hook_entity_delete). One of these is the hook you'll want to implement in your custom module, like so:
function mymodule_node_delete($node) {
// Perform some action based on values in $the node object.
// Nothing has been deleted from the database at this point.
}
You'll need to clear Drupal's caches again when you've added that hook but according to the documentation it should work.
I'm trying to extend a form and add an upload file field from within a module, I can see the file field just fine, but it's empty when I submit the form, the enctype is set.
$form['#attributes'] = array(
'enctype' => "multipart/form-data"
);
$form['file_upload'] = array(
'#type' => 'file',
'#title' => 'Attach Image'
);
custom form submit hook:
$form['#submit'][] = 'user_images_handler';
is being called, but when I dump the form, the file field is empty, and when I try to access it, it's empty as well.
File uploads are special in that the 'submitted' (uploaded) data does not end up in the form, but needs to be processed separately (uploading is not really a part of form submission but a separate transmission process).
See the docs for file_save_upload(), and as an example, see how it is used on form submission usage from within the upload module.
Basically, you just try to save the upload by calling file_save_upload() with the name of the upload field (and some other arguments) and check the result of this try.
Hmm, I tried that and it didn't work...it still says the upload field is empty.
I have a debugging print statement at the submit function but it doesn't print so I don't think it is even getting to the submit function.
Where are you suppose to put the file_save_upload() call?
Note, my form is named mmil_upload_form ( $form_state ) and the submit function is named function mmil_upload_form_submit ( $form, &$form_state )