I am building a complex AJAX based solution as a module into a Drupal 7 site. I decided not to write a standalone PHP script to respond to my jQUERY ajax call but implement the code within my drupal module.
My problem is establishing the connection between jQUERY and DRUPAL i:e the function which responds to my CLICK EVENT.
I was using the following code:
function staff_filter_menu(){
$items = array();
$items['staff/filtering/results/%'] = array(
'page callback' => 'staff_filter_function',
'access callback' => TRUE,
'type' => MENU_CALLBACK,
'delivery callback' => 'staff_filter_deliver',
);
$items['staff/filtering/saveclipboard'] = array(
'page callback' => 'staff_filter_savetoDB',
'access callback' => TRUE,
'type' => MENU_CALLBACK,
'delivery callback' => 'staff_filter_deliver',
);
drupal_flush_all_caches();
return $items;
}
But, it stopped working when I stopped, uninstalled and restarted the module. It seems to not be a reliable strategy.
drupal_flush_all_caches() does this:
Empties cache tables, rebuilds the menu cache and theme registries, and invokes a hook so that other modules' cache data can be cleared as well.
When the menu is rebuilt, hook_menu() is called...basically you're causing an infinite loop by putting drupal_flush_all_caches() where you currently have it.
You are still creating a loop where your menu items are being called, then cleared by the cache. If anything it should be called first, although there is another problem if you require this in your module's hook_menu().
You should remove that, and make sure your form is calling and returning data using fixed data.
Related
Starting off with a bit of background information, i have 3 models - Course, Pathway, Module.
Course HAS-MANY Pathway
Pathway HAS-MANY Module
Course HAS-MANY-THROUGH Module (through Pathway)
I have set up routes for creating Course, Pathway and Module. However, when I try to save the newly created model instance, it calls the wrong route method - does not even hit the store method of the relevant Controller
I understand that the order of the routes is important. I tried changing them around but it still does not work as intended.
Here's what I have so far
:
// modules
Route::get('/courses/{course}/edit/pathways/{pathway}/modules/create', [App\Http\Controllers\ModulesController::class, 'create'])->name('createModule');
Route::post('/courses/{course}/edit/pathways/{pathway}/modules', [App\Http\Controllers\ModulesController::class, 'store'])->name('storeModule');
// Pathways
Route::get('/courses/{course}/edit/pathways/create', [App\Http\Controllers\PathwaysController::class, 'create'])->name('createPathway');
Route::get('/courses/{course}/pathways/{pathway}/edit', [App\Http\Controllers\PathwaysController::class, 'edit'])->name('editPathway');
Route::delete('/courses/{course}/pathways/{pathway}', [App\Http\Controllers\PathwayController::class, 'destroy'])->name('destroyPathway');
Route::post('/courses/{course}/edit/pathways', [App\Http\Controllers\PathwaysController::class, 'store'])->name('storePathway');
// VQs/Qualifications
Route::resource('courses', App\Http\Controllers\CourseController::class, [
'names' => [
'index' => 'allCourses',
'create' => 'createCourse',
'store' => 'storeCourse',
'show' => 'showCourse',
'edit' => 'editCourse',
'update' => 'updateCourse',
'destroy' => 'destroyCourse',
]
]);
The problem is that when I try to store a Pathway or Module, it hits the Route::post('/courses/{course}') route.
I tried changing around the order of the routes, but none of that worked. I've also made sure that the create forms action is of the right Url Route. its all still the same.
I also can't tell which controller method is being called. Tried doing a dd() on CourseController#create, PathwaysController#create, ModulesController#create but none of them get hit.
Any help as to why this is happening will be greetly appreciated
Edit
here are some of my routes:
Since your URLs are quite similar.
How about refactoring your URL.
Also, writing a cleaner code would save you lots of headaches.
At the top:
<?php
use App\Http\Controllers\ModulesController;
use App\Http\Controllers\PathwaysController;
Route::name('modules.')->prefix('modules/courses')->group(function()
Route::get(
'{course}/edit/pathways/{pathway}/create', //e.g: modules/courses/engligh/edit/pathways/languages/create
[ModulesController::class, 'create']
)->name('create'); //modules.create
Route::post(
'{course}/edit/pathways/{pathway}',
[App\Http\Controllers\ModulesController::class, 'store']
)->name('store'); //modules.store
});
Route::name('courses.')->prefix('courses')->group(function()
Route::get(
'{course}/edit/pathways/create', //e.g: courses/english/edit/pathways/create
[PathwaysController::class, 'create']
)->name('create'); //courses.create
Route::get(
'{course}/pathways/{pathway}/edit',
[App\Http\Controllers\PathwaysController::class, 'edit']
)->name('edit');//courses.edit
Route::delete(
'{course}/pathways/{pathway}',
[App\Http\Controllers\PathwayController::class, 'destroy']
)->name('destroy');//courses.destroy
Route::post(
'{course}/edit/pathways',
[App\Http\Controllers\PathwaysController::class, 'store']
)->name('store');//courses.store
});
Run php artisan route:list to view your routes
Fixed it. Turns out there wasn't a problem with my routes at all.
The problem was that I had vertical navs and tab-panes on that page, and most of them had a form in them. I had not closed the form in one of the tab-panes and so this form was getting submitted to the action of the form above in that page.
i.e. Make sure to close forms using:
{{ Form::close() }}
Good day.
I created custom form in my module and defined submit button like this:
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save'),
'#ajax' => array(
'callback' => 'fmg_addbanner_ajax_callback',
'method' => 'replace',
'wrapper' => 'banner_add_wrapper'
)
);
Then outputted my form like this:
$form = drupal_get_form('fmg_banner_add_form', $region_id);
print render($form);
But ajax requests don't work. I think because of there are no needed drupal js files. How can I solve this problem? Thanks.
The normal case will be to have #ajax attached to a common input, like checkbox, text box etc.
The behavior is that when user change the input value, it'll fire your callback through ajax and send entire form over, and then you can process this form behind the scene and adjust certain things before sending the form back and change the element to the wrapper you defined.
One of the question that I had for partial form rendering is when I need to do some ajax call or inject partial form element to certain area of the page while keeping the integrity of the form rendering. (I don't know exactly what form build did, i guess i don't want to know)
Since form rendering uses the renderable array, if you just want to extract certain element, you could just do
$form = drupal_get_form('application_form');
$body = render($form['body']);
The following is a real example that i took a form and split into header, footer and the rest of form elements.
// get a form for updating application info.
$form = drupal_get_form('pgh_awards_review_application_form', $app);
$elements = array();
$form_render = render($form);
$elements = array(
'qualify' => render($form['qualify']),
'threshold_met' => render($form['threshold_met']),
'submit' => render($form['submit']),
);
if (preg_match('/<form.+div>/', $form_render, $matches)) {
$elements['header'] = $matches[0];
}
if (preg_match('/<input type="hidden".+form>/s', $form_render, $matches)) {
$elements['footer'] = $matches[0];
}
$vars['form'] = $elements;
It's definitely not pretty approach, it just serves the needs at the moment.
When I try to insert an image to the wysiwyg editor in Magento it places the right variable of the image path in the media directory.
But, wysigyg doesn't find the right path/url, example:
I inserted:
<p><img src="{{media url="wysiwyg/blog/Screen_Shot_2013.png"}}" alt="" /></p>
But, in the preview it gets me the next broken src:
<img src="https://localhost/index.php/admin/cms_wysiwyg/directive/___directive/e3ttZWRpYSB1cmw9Ii93eXNpd3lnL2Jsb2cvU2NyZWVuX1Nob3RfMjAxMy5wbmcifX0,/key/1a966015551bf00867319d23c9914b48/" alt="" data-mce-src="https://localhost/index.php/admin/cms_wysiwyg/directive/___directive/e3ttZWRpYSB1cmw9Ii93eXNpd3lnL2Jsb2cvU2NyZWVuX1Nob3RfMjAxMy5wbmcifX0,/key/1a966015551bf00867319d23c9914b48/">
And of course, it doesn't show the image. Also this happens with links and other media files.
System -> Configuration -> General -> Content Management -> Use Static URLs for Media Content in WYSIWYG for Catalog to Yes
The option wich Le Nguyen gave is not really a good solution.
Like hsanders said:
There are some pretty big drawbacks to doing this: The static URL will be a non-secure URL and If you change your base URL the URLs on the images will not update to reflect that are the two I can think of immediately.
A possible solution to "fix" the problem (not the right way in my opinion, but at least better than the static Url option) would be to add some code to the following file:
vendor/magento/module-catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php
Add on line 747:
'add_variables' => false,
'add_widgets' => false,
'add_directives' => true,
Also change
lib/web/mage/adminhtml/wysiwyg/tiny_mce/setup.js and add the following on line 384 (below content = editor.getContent();:
content = this.decodeContent(content);
Now you need to execute the following command to complete the process:
php bin/magento cache:flush
Hope this helps.
(Keep in mind you've just edited core files)
in your Form.php you configuration should be like below
protected function _prepareForm()
{
$model = Mage::registry('testimonial_data');
$form = new Varien_Data_Form();
$this->setForm($form);
$form->setHtmlIdPrefix('testimonial_');
$wysiwygConfig = Mage::getSingleton('cms/wysiwyg_config')->getConfig(array('add_variables' => false, 'add_widgets' => false,'files_browser_window_url'=>$this->getBaseUrl().'admin/cms_wysiwyg_images/index/'));
$fieldset->addField('content', 'editor', array(
'name' => 'content',
'label' => Mage::helper('testimonials')->__('Content'),
'title' => Mage::helper('testimonials')->__('Content'),
'style' => 'width:700px; height:500px;',
'state' => 'html',
'config' => $wysiwygConfig,
'required' => true,
));
}
hope it will work for you.
I think CakePHPs JsHelper is pretty neat to use for AJAX form submissions. Normally you just set the DOM element to update with the new content and the JsHelper takes care of the rest. A normal submit button could look like:
echo $this->Js->submit('Submit', array(
'update' => '#a-div',
'url' => 'some-url'
);
Now, I want to update 2 or 3 different DOM elements and my AJAX response type will be JSON with 2 or 3 key pairs. So to my question.
How can I capture the JSON response data and pass THAT DATA to an independent callback function that I have written myself where I can parse the response and update the relevant DOM elements with the value pairs? What is the correct syntax for that? I realise I could probably skip using the JsHelper and create my own submission, but I don't want to do that in this instance.
I found the right answer:
echo $this->Js->submit(
'Lägg en i varukorgen',
array(
'url' => array('controller' => 'products', 'action' => 'ajax_basket'),
'id' => 'basket-add-submit',
'success' => 'myFunction(data);',
)
);
At the success callback, data holds the JSON being returned.
Forget the JsHelper and write jquery code yourself.
I'm making a new widget for taxonomy term references where a submit button makes an ajax call back to drupal to alter the form. Here's what I have:
$element['my_module_wrapper']['add'] = array(
'#type' => 'submit',
'#value' => t('Add'),
'#ajax' => array(
'callback' => 'my_module_ajax',
'wrapper' => $field_name . '_my_module_container',
),
);
I have the ajax call working properly, but it validates the whole form, and throws errors when unrelated fields that are required aren't filled out. How can I stop this?
Also possibly related, it doesn't seem to call my hook_field_widget_form() function when ajax is called... is this stemming from the same problem?
Have you tried making your field #type = 'button' instead of 'submit'? As far as I know, a submit button will always run through the for validate array whether it's an ajax form item or not.
Look at the example from Poll module given here: http://api.drupal.org/api/drupal/developer--topics--forms_api_reference.html/7#ajax
The full function shows how it's done with '#limit_validation_errors'.