When the following (PrimeFaces) button is pressed
<p:commandButton value="Search"
actionListener="#{personController.searchPersons}"
update="resultTable"/>
I load a list of objects and display them in a table on the current page. This is done via an Ajax call.
Now I'd like to do the following: If only one object is found, don't update the result table but link directly to the "detail page". (e.g. detail.xhtml)
How can this be done?
I know that i can control the navigation via the return value of my searchPersons() method. But It doesn't work as it should. I think it has to do with the update="resultTable" of my button. But I currently don't know how to solve this...
You can bring in some JS in oncomplete attribute. It will be executed when the bean action and the partial update is completed. You can change the window location in JS by assigning window.location a new URL.
Here's a random kickoff example, assuming that you've a persons table with id persons and that the detail link look something like <a class="detail" href="detail.xhtml?id=123"> somewhere in the table row.
oncomplete="var $persons = jQuery('#persons tbody tr'); if ($persons.length == 1) window.location = $persons.find('a.detail').attr('href');"
Related
I am using wpdatatables to display data.
I have added MySQL Query in backend, and that query has 2 dynamic parameter like
SELECT some fields
FROM tbl1 tb1
JOIN tbl2 tb2
ON some conditions
JOIN tbl3 tb3
ON some conditions
WHERE DATE(Date) BETWEEN '%VAR1%' AND '%VAR2%';
wpdatatables Generate shortcode like [wpdatatable id=some_id] ,
I have create 2 date-picker for Start Date and End Date on Frontend.
Now I have to pass dynamic parameter like [wpdatatable id=some_id var1="strt_dt" var2="end_dt"]
So to get strt_dt and end_dt, I have call AJAX and pass parameters.
My problem is I am showing all this data inside popup.
I mean when user clicks on See Report Button
one popup will be open. Data also Displayed correctly. But it showing without wpdatatables Layout.
It is not Considering wpdatatables JS or CSS
Here is my AJAX Callback Function :
public function get_datatable_data() {
echo do_shortcode('[wpdatatable id=some_id var1="'.$_POST['strt_dt'].'" var2="'.$_POST['end_dt'].'"]');
wp_die();
}
Here is Code in which I am appending data :
var params = {"strt_dt":strt_dt,"end_dt":end_dt,action:"get_datatable_data"}
jQuery.post(ajaxurl,params,function(data){
if(data){
jQuery(".some class").empty().append(data);
}else{
jQuery(".some class").empty().append("No data Found");
}
This would have been possible if you are using normal datatable where you can re-initalize datatable on ajax success by using following code.
$("#div").dataTable().fnDestroy()
$("#div").dataTable();
But if you are using Plugin then there is no direct way to achive this, one possible solution is to create a normal page with datatable shortcode in it and then in you ajax callback you call that page in iframe.
for eg: you create page www.mysite.com/datatable - this page will have the actual shortcode
public function get_datatable_data() { ?>
<iframe src="www.mysite.com/datatable" height="200px"></iframe>
<?php
wp_die();
}
this will allow datatable to get initalize in iframe.
There is an issue I am facing in using pagination widget with ajax. What I am doing is, that I select category and then hit an ajax request to fetch the corresponding list by loading the data in the template and returning the html like this:
<f:if condition="{articles}">
<f:then>
<f:widget.paginate objects="{articles}" as="paginatedArticles" configuration="{itemsPerPage: numberOfRecords}">
<f:for each="{paginatedArticles}" as="article">
<h2>
<f:link.action action="show" arguments="{article : article}"> {article.title}</f:link.action>
</h2>
<p>
<f:format.html>{article.description}</f:format.html>
</p>
<hr/>
</f:for>
</f:widget.paginate>
</f:then>
<f:else>
No Records Found
</f:else>
And in my controller in my ajaxMethod I am simply doing
$this->view->assign('articles', $result); so it loads up the template with my result.
But now after rendering the ajax, if I use the pagination, the view breaks. There is no styling or header or anything.
This is how it shows up when I click the next on paginate widget: http://prntscr.com/kr8vg0
Just for completeness, here is the setup.txt which I have written that calls the ajax.
// PAGE object for Ajax call:
tt_content.list.20 = CASE
tt_content.list.20 {
key.field = list_type
}
ajax = PAGE
ajax {
typeNum = 1272
config {
disableAllHeaderCode = 1
disablePrefixComment = 1
additionalHeaders {
1526302502.header = Content-Type: text/html;charset=utf-8
}
}
10 = CONTENT
10 {
table = tt_content
select {
pidInList = this
orderBy = sorting
where = (list_type IN ("articleext_list"))
}
renderObj = < tt_content.list.20
}
}
Any help would be appreciated.
The typeNum that drives (should drive) XHR requests from widgets, is added from within the Fluid extension and does not require you to add a special PAGE object.
Even if you somehow made overrides that call your specific controller action it may not be treated correctly. Usually you would never refer to a content element instance but rather a straight Extbase request bootstrapping. Among other things, because rendering the content object adds wrappers.
So you should remove this and make sure you pass a QueryResult to the pagination widget. Then override the widget template if necessary. The rest should work without having to configure TS.
EDIT:
The pagination widget itself being used in a template that is rendered via XHR means it transfers the arguments you use to load the XHR - including the custom typeNum value. The widget then creates standard links that your click like normal - and they will be a link to the "inner content" of your XHR response because the URL contains a type number.
Here's where it gets bad: you cannot remove this typeNum once it is added. So you will have to instead cause the next/prev etc. links that are clicked, to cause a new XHR request that loads the content (how you do that very much depends on your JS application so can't guide you there).
My comment about ensuring a QueryResult is not relevant unless your pages don't change and you for example always see items 1-10.
But in order to solve this I would actually recommend that you do not use the pagination widget. The main reason being you're already in an XHR context that allows you to receive arguments for your controller action and manipulate the offset and limit parts of the query from within your controller action. That means you can generate your links not to the widget but to the controller action, and for example put a CSS class on the links that should trigger XHR requests vs. those that should reload the entire page (for example to show a detail view). You avoid having to override the pagination template and you control all parameters of all links.
In fact, I would favor a controller argument for offset above using the pagination widget regardless of XHR or not. There's a long list of technical reasons why that I won't list here but suffice it to say, trading a lot of "black box" for having to create a single argument is a very reasonable and predictable-result thing to do.
Is there any way to know that view is open by back?
For example
<div data-role="view" id="view-test" data-show="show">
<!-- View content -->
</div>
<script>
var show = function(e){
if(e.view.isBack())
{
console.log("Back")
// do something
}
}
</script>
Is there any method or property like e.view.isBack() ?
There are many ways to handle this, maybe you can use a global variable where you keep the last visited page or even you can add a back button handler and get the view from which the back button was pressed. Another solution would be to pass a parameter along with page navigation when going back, for example:
<a data-role="button" href="#foo?back=true">Link to FOO with back parameter set to true</a>
And on the visited page on show event you can get the parameter like this:
function fooShow(e) {
e.view.params // {back: "true"}
}
Now depending on what the parameter value is you can detect if the back button was pressed or not before reaching the page.
Basically what i want is that in my view file i have a list of various restaurants,and in front of each of them is a "show" button,which on clicking should display three more buttons(dynamically),where each button performs some action regarding the corresponding restaurant name(like show menu,show reviews)(this action should be dynamic too). Can anybody help me with this implementation.
In the view you can place a link and a target container:
{{=A('the link', callback=URL('controller', 'function', args=[my_arg]), target="callback-target", _class="btn btn-default")}}
<div id="callback-target"></div>
If the link is clicked the function in controller is called and you can read the argument my_arg with:
def function():
data = request.args(0)
response.flash('Data received!')
return DIV('Return anything ...')
The returned data is displayed in <div id="callback-target"></div>
I have a view with a button and a DIV
I am trying to have this kind of functionality:
if the button is clicked - a controller method is executed ( i have the method, db.insert, etc.)
- if test (inside the controller method) is passed the button dissapears and the div appears ( I thought at using ajax - not to refresh the hole page)
whenever the page is refreshed the test has to be made again for the button to be visible or not
thanks
Something like this?
{{=DIV(A('click me',callback=URL('mycallback'),target="me"),_id="me")}}
def mycallback():
# do whatever you need to do
return DIV("I will appear in place of he link when you click")
I looked in more of your examples and I think my problem was simpler ( if there isn't any other solution)
So what I did was I used eval:
button in view :
<input id="b_normal" type="button" value="normal" onClick="ajax('{{=URL('db_test')}}',[],':eval')" />
and the controller method:
def db_test()
#tests and updates
return "jQuery('#b_normal').fadeOut();jQuery('#commDiv').show();"
for further refresh i used jquery, in view:
jQuery(document).ready(function(){
var flag = '{{=flag_normal}}';
if(flag == 'da')
jQuery('#b_normal').hide();
else jQuery('#commDiv').hide();
});
where *flag_normal* is sent by the main controller
I hope this is not too inefficient and if so, useful