Load drupal view into right margin with ajax - ajax

I'm using Drupal 6 and have created 2 equal columns in layout.css
In the left column I have a view with a list of nodes.
Each node has an attached view with a list of it's child nodes (using views attach and a node reference argument).
I would like to be able to click a link on each of these left column nodes and bring up it's child view in the right column using ajax.
I've tried placing jquery/javascript in the head of the node-xxx.tpl.php calling the viewsattach via an external page named ajaxview.php ie:
<script type="text/javascript">
Drupal.behaviors.ajaxview = function(context) {
$("#ajaxclick").click(function(){
$("#container").load("http://path/to/ajaxview.php
});
}
</script>
<a id="ajaxclick" href= "#">Click me</a>
<div id="container"></div>
And in ajaxview.php :
<div id="rightcolumn"><?php print $node->content[Comments_node_content_1]['#value'];?></div>
I get nothing but a blank page...
How can I get a child view to appear in the right column whenever a node in the left column is clicked?
Is there a better way?

Your ajaxview.php file is not in the same context as your code in node-xxx.tpl.php and that means that it does not have access to $node variable. Your ajaxview.php file is executed as a new script, probably outside Drupal if you really named it ajaxview.php.
You should consider creating a path in your menu hook and call that path with ajax in your node-xxx.tpl.php.
<?php
function test_menu() {
$items = array();
$items['myajax'] = array(
'title' => 'My Ajax',
'page callback' => 'test_myajax',
'description' => 'Test',
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
);
return $items;
}
function test_myajax($nid) {
$node = node_load($nid);
print '<div id="rightcolumn">';
print $node->content['Comments_node_content_1']['#value'];
print '</div>';
exit();
}
This code will create a new path "myajax" (which you should rename to something more meaningfuyl to you) which should be called with a node id like this:
http://yoursite/myajax/999
where 999 is the node id.
This means that in your code that calls the ajax, you should pass the nid of the current node being viewed. There are different ways of doing this, depends on your context.
Here is a sample javascript that works with the code above (I tested it local).
<script type="text/javascript">
Drupal.behaviors.ajaxview = function(context) {
$("#ajaxclick").click(function(){
$("#container-test").load(Drupal.settings.basePath + "myajax/" + 999);
});
}
</script>
<a id="ajaxclick" href= "#">Click me</a>
<div id="container-test"></div>

Related

Call view in Laravel Controller with anchor tag

I need to call a view in a Laravel Controller, with parameters and with Anchor Tag.
I have this code in my controller:
return view('plans/editPlanView',
['plan' => $plan,
'patient' => $patient,
'aliments'=>$aliments, 'menu'=>$menu, 'tabName'=>$tabName]);
But i need to add an Anchor tag to land in a specific section of the page.
I can't use
return Redirect::to(URL::previous() . "#whatever");
proposed in other posts because i need to pass some parameters.
I think there are some base problem, trying with console this:
$('html, body').animate({
scrollTop: $('#whatever').offset().top
}, 1000);
scrolling to the desired section does not work.
it seems the page makes a small snap but always returns to the top.
Update
I have found the cause of the problem. At the bottom of the blade page I have the following code, without it the anchor tag works fine. Adding it the page makes a small scroll to return to the head. I need to use the datepicker, how can I fix the problem and get the anchor tag to work?
#push('scripts')
<script type="text/javascript">
$(document).ready(function () {
$('.date').datepicker({
firstDayOfWeek: 1,
weekDayFormat: 'narrow',
inputFormat: 'd/M/y',
outputFormat: 'd/M/y',
markup: 'bootstrap4',
theme: 'bootstrap',
modal: false
});
});
</script>
#endpush
You can create the method showPage() in your contoller for example TestController
public function showPage(Request $request)
{
$plan = $request->plan;
...
return view('plans/editPlanView', [
'plan' => $plan,
'patient' => $patient,
'aliments'=>$aliments, 'menu'=>$menu, 'tabName'=>$tabName
]);
}
Then create a route for rendering that view
Route::get('/someurl', 'TestController#showPage')->name('show-page');
And then in your methods you can use something like that:
$url = URL::route('show-page', ['#whatever']);
return Redirect::to($url)
I found a workaround, I added the disable attribute to the date input, in doing so, when the datepicker is initialized, the page does not scroll up. Then, as a last javascript statement I re-enabled the fields:
$('.date').prop("disabled", false);

External Template for Column ClientTemplate

I have an issue on having an external template inside Column ClientTemplate
.Columns(col =>
{
col.Bound(c => c.ID);
col.Bound(c => c.Name).Width(100);
col.Bound(c => c.StatusID)
.Title("Action")
.ClientTemplate("#=_actionTemplate(data)#")
.Width(100);
})
<script id="tmplAction" type="text/x-kendo-template">
#(Html.Kendo().Button().Name("btnTest_#=ID#")
.Content("Test")
.ToClientTemplate())
</script>
<script>
var _actionTemplate = kendo.template($('#tmplAction').html());
</script>
Even though it is called and rendered inside the grid column, kendo script is not executed therefore the only rendered element is a basic Button and not Kendo Button
Any help would be appreciated
Copied from your code :
.ClientTemplate("#= fnactionTemplate(data)#")
And declare that function like:
function fnactionTemplate(data){
// External logic goes here....
return $('#tmplAction').html();
}
Hope it will work.

Kendo Grid Multiple Hyperlinks in single column

I am using following code to display data from server in a Kendo Grid.
Working fine.
I want to put two hyperlinks in last cell of each row, but can do with only one.
I want EDIT and DELETE link in same cell.
How can I achieve this?
CODE
#(Html.Kendo().Grid(Model)
.Name("Grid")
.Columns(columns =>
{
columns.Bound(u => u.USERNAME);
columns.Bound(u => u.PASSWORD);
columns.Bound(u => u.ROLE);
columns.Bound(u => u.STATUS);
columns.Template(c => Html.ActionLink("Edit", "Edit", new { id = c.ID }));
}
)
.Pageable()
)
There are a couple of ways to do this.
First you could use the inbuilt edit/delete options from within the grid config
like so:
columns.Command(command =>
{
command.Edit();
command.Destroy();
});
Then just wire up the edit config and destroy delete commands appropriately.
Alternatively you can template these out using one of two methods:
First inline template:
columns.Bound(c => c.ID).ClientTemplate("<a href='Edit/#=data.ID#'>Edit Link #=data.ID#</a>
<a href='Delete/#=data.ID#'>Delete Link #=data.ID#</a>")
So this is just bound to a column and the template is added as per your requirements using standard html and javascript if required. This is fine for simple things but can get very clunky fast if you have more complex templates which then leads to the second method creating a template and calling that like this:
columns.Bound(c => c.ID).ClientTemplate("#=getButtonTemplate(data,'buttonsTemplate')#")
then create your template like so:
<script id="buttonsTemplate" type="text/x-kendo-template">
<div class='btn-group'>
<a class="btn btn-primary" href='#Url.Action("{edit action}", "controller")/#=ID#'>Edit Link #=ID#</a>
<a class="btn btn-danger" href='#Url.Action("{delete action}", "controller")/#=ID#'>Delete Link #=ID#</a>
<div>
</script>
then the getButtonTemplate function:
function getButtonTemplate(data, templateName) {
var templateObj = $("#" + templateName).html();
var template = kendo.template(templateObj);
return template(data);
}
So let me explain what is going on here with this second method.
Instead of templating the html in the column we extract it out into two components for want of a better word.
We use the getButtonTemplate function to pass 2 params in the data item and the template's id. This function simply loads the passed data object into the template and the kendo magic renders the html and injects the values in as required. Check the kendo demo site for more info on this subject.
The template element can be a mix of html and javascript so if you needed to apply some logic in the template this can be done in here. Again refer to the kendo site for more info on this subject.
I personally prefer the second method of doing this client templating as it is easier to manage and make changes without rogue hash's or brackets breaking code.
If you need any more info let me know and I will update the answer for you.

Yii ClientSide Validation on Render Partial not Working

I have a Yii form which calls a render partial from another model (team has_many team_members). I want to call via ajax a partial view to add members in team/_form. All works (call, show, save) except for ajax validations (server and client side). If i submit form, member's model isn't validating, even in client side, it's not validating the required fields.
Any clue?
//_form
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'team-form',
'enableAjaxValidation'=>true,
'enableClientValidation'=>true,
'clientOptions'=>array(
'validateOnSubmit'=>true,
'validateOnChange'=>true
),
'htmlOptions' => array('enctype' => 'multipart/form-data'),
)); ?>
//Controller
public function actionMember($index)
{
$model = new TeamMember();
$this->renderPartial('_member',array(
'model'=> $model, 'index'=> $index
)
,false,true
);
}
public function actionCreate()
{
$model=new Team;
$members = array();
if(isset($_POST['Team']))
{
$model->attributes=$_POST['Team'];
if(!empty($_POST['TeamMember'])){
foreach($_POST['TeamMember'] as $team_member)
{
$mem = new TeamMember();
$mem->setAttribute($team_member);
if($mem->validate(array('name'))) $members[]=$mem;
}
}
$this->redirect(array('team/create','id'=>$model->id,'#'=>'submit-message'));
}
$members[]=new TeamMember;
$this->performAjaxMemberValidation($members);
$this->render('create',array(
'model'=>$model,'members'=>$members
));
}
//_member
<div class="row-member<?php echo $index; ?>">
<h3>Member <?php echo $index+1; ?></h3>
<div class="row">
<?php echo CHtml::activeLabel($model, "[$index]name",array('class'=>'member')); ?>
<?php echo CHtml::activeTextField($model, "[$index]name",array('class'=>'member')); ?>
<?php echo CHtml::error($model, "[$index]name");?>
</div>
</div>
ProcessOutput was set to true. No dice.
Switch renderPartial() to render(). No dice.
If you will look at the CActiveForm::run:
$cs->registerCoreScript('yiiactiveform');
//...
$cs->registerScript(__CLASS__.'#'.$id,"jQuery('#$id').yiiactiveform($options);");
Then you will understand that you validation will not work, because you render partial and not the whole page. And these scripts show up at the bottom of the page. So you should solve this by execute these scripts.
After you partial is rendered, try to get activeform script which should be stored at the scipts array:
$this->renderPartial('_member',array('model'=> $model, 'index'=> $index));
$script = Yii::app()->clientScript->scripts[CClientScript::POS_READY]['CActiveForm#team-form'];
after, send it with rendered html to page:
echo "<script type='text/javascript'>$script</script>"
Also remember before you will append recieved html on the page you should include jquery.yiiactiveform.js, if you not already did it(by render another form, or registerCoreScript('yiiactiveform')), on the page from calling ajax request. Otherwise javascript error will raised.
Hope this will help.
Edit:
Sorry I'm not understood that you are render part of form and not the whole. But you validation will not work exactly with the same issue. Because jQuery('#$id').yiiactiveform($options); script was not created for the field.
The actual problem is that the ActiveForm saves its attributes to be validated in the "settings" data attribute. I see you are already using indexes so what you need to add the new elements to this settings object in order for the validation to work. After the ajax response this is what must be done:
//Get the settings object from the form
var settings = $("#form").data('settings');
//Get all the newly inserted elements via jquery
$("[name^='YourModel']", data).each(function(k, v) {
//base attribute skeleton
var base = {
model : 'YourModel',
enableAjaxValidation : true,
errorCssClass : 'error',
status : 1,
hideErrorMessage : false,
};
var newRow = $.extend({
id : $(v).attr('id'),
inputID : $(v).attr('id'),
errorID : $(v).attr('id') + '_em_',
name : $(v).attr('name'),
}, base);
//push it to the settings.attribute object
settings.attributes.push(newRow);
});
//update the form
$("#form").data('settings', settings);
```
This way the ActiveForm will be aware of the new fields and will validate them.
Well, setting processOutput to true in renderPartial (in order to make client validation works on newly added fields) will not help in this case since it will only work for CActiveForm form and you don't have any form in your _member view (only input fields).
A simple way to deal with this kind of problem could be to use only ajax validation, and use CActiveForm::validateTabular() in your controller to validate your team members.

Cakephp with Ajax, this.element.setAttribute is not a function

I'm trying to make a stackoverflow like tags system.
I followed this tutorial (in French): http://www.formation-cakephp.com/34/autocomplete-en-ajax which uses Prototype and Scriptaculous. Of course, I adapted it to my project
I get the following error:
this.element.setAttribute is not a function : controls.js Line 86
which corresponds to
this.element.setAttribute('autocomplete','off');
in the control.js file
I'm really new to Ajax, so I don't have a clue on what I'm doing (wrong)...
If you need some code from any file, let me know!
view.ctp:
<div class="input">
<label>Tags :</label>
<?php e($ajax->autoComplete(
'Tag.tag',
'/tags/autocomplete',
array(
'minChars' => 3,
'indicator' => 'ajaxloader'
)
)); ?>
<div id="ajaxloader" style="display:none;">
Chargement...
</div>
Controller:
function autocomplete()
{
$recherche = utf8_decode($this->data['Tag']['tag']);
$tags = $this->Tag->find(
'all',
array(
'fields' => 'DISTINCT tag',
'conditions' => "tag LIKE '$recherche%'",
'order' => 'tag',
'limit' => 10
)
);
$this->set(compact('tag', 'recherche'));
}
jQuery, scriptaculous, & prototype don't play well together but you can resolve this issue by putting jQuery in no-conflict mode.
var $j = jQuery.noConflict();
// $j is now an alias to the jQuery function; creating the new alias is optional.
Now instead of using the $ to for jQuery use $j so for example:
$j(document).ready(function() {
$j( "div" ).hide();
});
For more information on avoiding jQuery conflicts refer to the following: https://learn.jquery.com/using-jquery-core/avoid-conflicts-other-libraries/
It appears that scriptaculous doesn't play well with j-query. When I removed the j-query link I stopped getting an error. This definitely isn't an ideal solution, but I thought I'd share my discovery.

Resources