I have created a ModalDialog in Drupal contain two forms like as follows,
public function signUpForm() {
$response = new AjaxResponse();
// Get the modal form using the form builder.
$modal_form[] = $this->formBuilder->getForm('Drupal\signup_form\Form\SignupForm');
$modal_form[] = $this->formBuilder->getForm('Drupal\signup_form\Form\SigninForm');
// Add an AJAX command to open a modal dialog with the form as the content.
$response->addCommand(new OpenModalDialogCommand('', $modal_form, ['width' => '800','dialogClass' => 'signup-modal']));
return $response;
}
The forms are rendered, But the problem is ,both forms are submitting to the same function. I am unable to change the action of the form.
Is there any options available to change the form action to a custom url?
You need to alter these forms so that you can add your own submit handlers (and remove the unwanted one), and eventually from there you will be able to set the appropriate redirect, or AjaxResponse.
For example, for each form, implement hook_form_alter from a custom module :
function MODULE_signup_form_alter(&$form, FormStateInterface $form_state, $form_id) {
$form['actions']['submit']['#attributes']['class'][] = 'use-ajax-submit';
$form['actions']['submit']['#submit'][] = 'MODULE_signup_form_ajax_submit';
}
Then add the appropriate submit handlers, eg. :
function MODULE_signup_form_ajax_submit(array $form, FormStateInterface &$form_state) {
$response = new AjaxResponse();
$form-class = '.signup-form'; # using your own selector
$selector = '#drupal-modal' . ' ' . $form-class;
$message = '<div>submitted</div>';
$response->addCommand(new ReplaceCommand($selector, $message));
$form_state->setResponse($response);
}
I assumed you want to update the modal content so that the second form can still be submitted, so here I added the 'use-ajax-submit' class (cf. Drupal.behaviors.AJAX) to the appropriate $form action attributes so that the submit response can be rendered in the modal as well. Also used the ReplaceCommand to replace the submitted form content with a simple message.
If instead the first submitted form should trigger a redirection, then don't use setResponse() (that actually cancels redirect), and use setRedirect() if the base action url is not the one that you want.
Related
I am using form helper library to load form in ci views. the script i am using is
echo form_open('');
But when i am inspeting the form or having a look at page source it has set action attribute with base url. I want to set action attribute always blank when using form_open('') method. How can i get this behavior of form_open() method. Usually we set action like this when using ci standard
echo form_open('abc/login');
so is there a way to keep action attribute blank.
First of all load a view in your view page of form open
View.php
// Open Form
<?php $this->load->view('your_directory_path/form_open'); ?>
Secondly add form open code in seperate file so it can be attached anywhere in view files.
form_open.php
<form method="post" id="XYZ_DEMO" name="XYZ_DEMO" enctype="multipart/form-data" class="ABC XYZ">
like this you can set action attribute blank using form_open in codeigniter.
First of load form helper in order to use form_open() method.
$this->load->helper('form');
Or load helper in application/config/autoload.php.
Then set blank form action attribute in view. like this..
<?php echo form_open('', array('id' =>'form_id', 'class'=>'form_class'); ?>
Not sure what you are trying to achieve by wanting the action attribute blank.
If you look into CI's form_open function inside the form_helper:
function form_open($action = '', $attributes = '', $hidden = array())
{
$CI =& get_instance();
if ($attributes == '')
{
$attributes = 'method="post"';
}
// If an action is not a full URL then turn it into one
if ($action && strpos($action, '://') === FALSE)
{
$action = $CI->config->site_url($action);
}
// If no action is provided then set to the current url
$action OR $action = $CI->config->site_url($CI->uri->uri_string());
$form = '<form action="'.$action.'"';
$form .= _attributes_to_string($attributes, TRUE);
$form .= '>';
/* MORE CODE */
}
you can see that if the $action parameter is not set, it will be set to the current url.
// If no action is provided then set to the current url
$action OR $action = $CI->config->site_url($CI->uri->uri_string());
that could be the reason why when you pass empty parameter to form_open('') the action attribute still has value.
wouldn't it hurt if you just use html's way?
<form action="" method="post" id="form_upload_submit">
if you really really know what you want to do, go ahead and edit (which I don't really advise doing so) the form_open function inside the form_helper.php located in system\helpers\form_helper.php
Blank action points to current page so that you can use
echo form_open(base_url());
I want to validate my Yii2 activeform on simple button click which is not submitButton. I tried $('#formId').yiiActiveForm("validate") but it is not working.
I also tried - $('#formId').yiiActiveForm('submitForm') it validates form but it also submit it if everything is ok. I don't want to submit that form. I just want to validate it on button click and if everything is ok than i want to open a modal popup.
What are possible ways to validate this activeform on button click
To validate your form perform ajax validation only inside your action as follows. This will only validate your form
public function actionValidateForm() {
$model = new Form();
if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
Yii::$app->response->format = Response::FORMAT_JSON;
return ActiveForm::validate($model);
Yii::$app->end();
}
}
You have to set enableClientValidation = false, in you'r form's options .
I'm building a contact form in SilverStripe.
When testing validation, if I leave the required fields blank and hit submit, those input fields will be added a .holder-required class. Even if I reload the page, they won't disappear. (actually the error messages *** is required will stay there after reload too. I just stopped the messages from showing).
I've searched the whole project folder, but there's no file that even has holder-required in it.
Where does the .holder-required class come from?
The reason why you couldn't find holder-required is because it technically doesn't exist in the SilverStripe codebase, it actually is a class that is concatenated together from two strings.
In a FormField, there is a function called "extraClass" which adds these classes to the field.
Below is the snippet of code from the FormField class:
public function extraClass() {
$classes = array();
$classes[] = $this->Type();
if($this->extraClasses) {
$classes = array_merge(
$classes,
array_values($this->extraClasses)
);
}
if(!$this->Title()) {
$classes[] = 'nolabel';
}
// Allow custom styling of any element in the container based on validation errors,
// e.g. red borders on input tags.
//
// CSS class needs to be different from the one rendered through {#link FieldHolder()}.
if($this->Message()) {
$classes[] .= 'holder-' . $this->MessageType();
}
return implode(' ', $classes);
}
What this tells us is that for a message that appears for a field, it will append holder-{Whatever_Your_Message_Type_Is} as an extra class.
The reason why $this->Message() would still be set after a page reload is that the error information is actually saved to the session for that form.
Below is a snippet from the Form class which is what calls the FormField::setError(), the function that sets the message property on the form field.
public function setupFormErrors() {
$errorInfo = Session::get("FormInfo.{$this->FormName()}");
if(isset($errorInfo['errors']) && is_array($errorInfo['errors'])) {
foreach($errorInfo['errors'] as $error) {
$field = $this->fields->dataFieldByName($error['fieldName']);
if(!$field) {
$errorInfo['message'] = $error['message'];
$errorInfo['type'] = $error['messageType'];
} else {
$field->setError($error['message'], $error['messageType']);
}
}
// load data in from previous submission upon error
if(isset($errorInfo['data'])) $this->loadDataFrom($errorInfo['data']);
}
if(isset($errorInfo['message']) && isset($errorInfo['type'])) {
$this->setMessage($errorInfo['message'], $errorInfo['type']);
}
return $this;
}
I've had a bit more of a browse of the Form code, it should be clearing the errors after it is rendering the form. There are two functions part of the form class, clearMessage and resetValidation.
The function clearMessage is called when rendering the form template through forTemplate. I do not see any usage of the resetValidation function throughout the SilverStripe CMS or Framework codebases.
You may need to potentially call one or the other in your code if under your circumstances the message is not clearing.
This has to do with routing. So for getting parameters via url, you basically pass the data to the url following the route format you set.
This is working with links. I created the route, passed the data into the url, and used the request method to get the parameter for use in the controller. like URL::site("site/$color/$size")
What if I am constructing the url by form submission? For example, if I want to create a basic search query.
How do I get my form submission to look like this search/orange/large and not like this search.php?color=orange&size=large when I submit a form via get method.
By definition, the GET method puts the submitted information as URL parameters. If you specifically want to end up with a URL like site/$color/$size, you can use the POST-REDIRECT-GET pattern.
A partial example, from a controller on one of my sites (there is a submit button on the page named clear_cache_button):
public function action_index()
{
$session = Session::instance();
$is_post = (Request::current()->post('submit_button') !== NULL);
$is_clear_cache = (Request::current()->post('clear_cache_button') !== NULL);
$p = Database::instance()->table_prefix();
$people = DB::query(Database::SELECT, "
SELECT *
FROM `".$p."Tabe`;
")->cached(600, $is_clear_cache)->execute()->as_array('RegID');
if ($is_clear_cache)
{
HTTP::redirect(Request::current()->uri());
}
...
...
...
}
You can use Route filters (v3.3) or callbacks (3.1, 3.2) and set route params manually.
You can do it this way...
public function action_index()
{
// this will only be executed if you submmitted a form in your page
if(Arr::get($_POST,'search')){
$errors = '';
$data = Arr::extract($_POST,array('color','size'));
// you can now access data through the $data array:
// $data['color'], $data['size']
// perform validations here
if($data['color']=='') $error = 'Color is required';
elseif($data['size']=='') $error = 'Size is required';
if($error==''){
$this->request->redirect('search/'.$data['color'].'/'.$data['size']);
}
}
// load your search page view here
echo 'this is the search page';
}
Hope this helps you out.
I'm using Cake 2.1, and with it comes the new JsonView. What I'd like to do is POST to a method in my controller and render an html fragment so that I can return it as a value in json.
Previously I'd do something like this:
public function ajaxSubmit() {
if (!$this->request->is('ajax')) {
$this->redirect('/');
} else {
$this->autoRender = $this->layout = false;
$message = 'Please enter a message';
$this->set('message');
$errorFragment = $this->render('/Elements/errors/flash_error');
$toReturn = array('errorFragment' => $errorFragment);
return json_encode($toReturn);
}
}
Which only sends back the html fragment of that particular flash_error element such that I can't have multiple key => values being sent back in a standard json object. I want to be able to send both html fragments and just plain text as json.
So my question really is, how can I render an HTML element and set it with a (key=>value pair) to be sent back as json from my controller using the JsonView that Cake 2.1 provides? I already have set in my routes file Router::parseExtensions('json'); and I'm including the RequestHandler component inside of my AppController.
You shouldn't need a separate action for AJAX when using data views. Use can use the same action as your non AJAX submit.
However assuming that you wish to use a different action for AJAX because I don't know what your other action looks like, you can write something like this in app/View/ControllerName/json/ajaxSubmit.ctp.
<?php
$errorFragment = $this->element('errors/flash_error');
$toReturn = array('errorFragment' => $errorFragment);
echo json_encode($toReturn);
Then change your action to this
public function ajaxSubmit() {
if (!$this->request->is('ajax')) {
$this->redirect('/');
} else {
$message = 'Please enter a message';
$this->set('message');
}
}
See "Using a data view with view files" in the documentation.