I am trying to update yii2 grid view using pjax on keypress, Like by default in Yii2 grid view searching works on blur or on change event.
What I am looking for to overwrite this functionality on keypress.
Any help will be greatly appreciated. Thanks.
You should do following:
Disable default submit events and bind keyup event on filter inputs.
Focus active input after updating
Here is a simple working example:
var input;
var submit_form = false;
var filter_selector = '#grid-id-filters input';
$("body").on('beforeFilter', "#grid-id" , function(event) {
return submit_form;
});
$("body").on('afterFilter', "#grid-id" , function(event) {
submit_form = false;
});
$(document)
.off('keydown.yiiGridView change.yiiGridView', filter_selector)
.on('keyup', filter_selector, function() {
input = $(this).attr('name');
if(submit_form === false) {
submit_form = true;
$("#grid-id").yiiGridView("applyFilter");
}
})
.on('pjax:success', function() {
var i = $("[name='"+input+"']");
var val = i.val();
i.focus().val(val);
});
View:
<?php \yii\widgets\Pjax::begin(['id' => 'pjax-id']) ?>
<?= GridView::widget([
'id' => 'grid-id',
'dataProvider' => $dataProvider,
'filterModel' => $filterModel,
'columns' => [
'id',
'title'
]
]);?>
<?php \yii\widgets\Pjax::end(); ?>
Related
I manage a list of related elements in my form with a MUIDataTable(encapsulated here as CrudList) and a MUI Autocomplete.
I managed to add new elements through the autocomplete components onChange and to remove an element from a button using almost the same code. But I need to add .value on the second case Or it doesn't re-render.
What I'm doing wrong?
function RelatedModels({name, value ,model, tittle, columns, optionsSelector, onChange, ...fc}) {
const formik = useFormikContext();
const options = useSelector(createSelector(optionsSelector,
elements=> elements.filter(item => ! value.some(s=> item.idx === s.idx)))
);
const buttons = [
quickButton(
idx => () => {
const a =fc;
debugger;
//THIS NOT RE ENDER
formik.values[name]= value.filter(elem => idx !== elem.idx);
formik.setFieldTouched(name, true, false);
}
, 'Eliminar', <Delete/>)
];
return (
<Paper className="formPanel">
<h1>{tittle}</h1>
<Autocomplete
options={options}
onChange={(o, newElement)=> {
// THIS RE RENDER THE COMPONENT
formik.values[name].value = value.push(newElement);
formik.setFieldTouched(name, true, false);
}}
renderOption={ (option, state) =>
<span>{option.name}</span>
}
renderInput={params =>(
<MuiTextField {...params} label="Select to add" margin="normal" fullWidth/>)
}
/>
<CrudList Model={model} columns={columns.concat(buttons)} elements={value} buttons/>
</Paper> );
}
I include the component in the Formik as Follows
<Field as={RelatedModels}
name="accessories" model={Accessory} optionsSelector={availableAccessories}
tittle="Selecciona accesorio a aƱadir"
columns={accessoriesColumns}
/>
On my xPage I have just a panel and editBox inside.
<xp:panel id="panel1">
<xp:inputText id="inputText1">
<xp:eventHandler event="onkeydown" submit="true"
refreshMode="partial" refreshId="panel1">
</xp:eventHandler></xp:inputText>
</xp:panel>
by pressing Enter key in editBox I want to refresh my panel1 and then return focus to my edit box inputText1.
P.S. it's supposed there are other components on that panel this is why I want to refresh it once user enter something into editbox and press Enter key. Any focus() set code doesn't work once you refresh the panel either into onkeydown event or in onComplete of eventhandler. But you can set the focus if you ouside of that panel (e.g. new button with onclick event "...focus())"
Pressing the enter key is a normal function to receive via a JavaScript listener. Triggering a partial refresh can also be done from JavaScript via the client-side XSP object. Here's how a basic implementation would look.
<xp:panel
id="panel1">
<xp:inputText
id="inputText1">
<xp:eventHandler
event="onkeydown"
submit="false"
id="eventHandler1"
execMode="partial">
<xp:this.script><![CDATA[if(event.keyCode == 13){
event.preventDefault();
XSP.partialRefreshPost("#{id:panel1}",{
onComplete: function(){
document.getElementById("#{id:inputText1}").focus();
}
});
}]]></xp:this.script>
</xp:eventHandler>
</xp:inputText>
</xp:panel>
Edit:
I forgot to use event.preventDefault() on the enter action. I confirmed this as working in a sample XPage, shown here. Alternatively, in place of the focus call, you could use a select to highlight existing text, or do something else to put the cursor at the end of the field.
I wrote a general purpose snippet a while back that tries to counteract the effect of partial refresh on focus states. If I understand your issue correctly, this would remove the need to "hard code" which field you want to have focus after the refresh. You will also need the snippet for hijacking partial refreshes.
I think the only thing you need to to to the field after you've added the two snippets is to make sure that the event handler/partial refresh only fires on the enter key.
In client script: return ( thisEvent.keyCode === 13 );
Code snippet for hijacking partial refreshes:
function hijackAndPublishPartialRefresh(){
// Hijack the partial refresh
XSP._inheritedPartialRefresh = XSP._partialRefresh;
XSP._partialRefresh = function( method, form, refreshId, options ){
// Publish init
dojo.publish( 'partialrefresh-init', [ method, form, refreshId, options ]);
this._inheritedPartialRefresh( method, form, refreshId, options );
}
// Publish start, complete and error states
dojo.subscribe( 'partialrefresh-init', function( method, form, refreshId, options ){
if( options ){ // Store original event handlers
var eventOnStart = options.onStart;
var eventOnComplete = options.onComplete;
var eventOnError = options.onError;
}
options = options || {};
options.onStart = function(){
dojo.publish( 'partialrefresh-start', [ method, form, refreshId, options ]);
if( eventOnStart ){
if( typeof eventOnStart === 'string' ){
eval( eventOnStart );
} else {
eventOnStart();
}
}
};
options.onComplete = function(){
dojo.publish( 'partialrefresh-complete', [ method, form, refreshId, options ]);
if( eventOnComplete ){
if( typeof eventOnComplete === 'string' ){
eval( eventOnComplete );
} else {
eventOnComplete();
}
}
};
options.onError = function(){
dojo.publish( 'partialrefresh-error', [ method, form, refreshId, options ]);
if( eventOnError ){
if( typeof eventOnError === 'string' ){
eval( eventOnError );
} else {
eventOnError();
}
}
};
});
}
Code snippet for remembering focus states:
dojo.addOnLoad(function(){
dojo.subscribe( 'partialrefresh-init', function(){
// setTimeout needed to make it work in Firefox
setTimeout(function(){
var activeElementId = document.activeElement.id;
var focusSubscription = dojo.subscribe( 'partialrefresh-complete', function(){
// Only set focus if field hasn't been overwritten/lost focus
if( document.activeElement.id !== activeElementId ){
var activeElement = dojo.byId(activeElementId);
if( activeElement && /INPUT|SELECT|TEXTAREA/.test( activeElement.nodeName ) ){
// Set focus to element/select text
activeElement.focus();
if( activeElement.nodeName !== 'SELECT' ){
activeElement.select();
}
}
}
// Unsubscribe after focus attempt is done
dojo.unsubscribe( focusSubscription );
});
// In case of error -> remove subscription
var errorSubscription = dojo.subscribe( 'partialrefresh-error', function(){
dojo.unsubscribe( focusSubscription );
});
}, 0 );
} );
});
First data loading is fine but when i click on load more my second page data going inside even div only.
I am generating list like this:
<div class="odd">
<items>item1</items>
<items>item3</items>
<items>item5</items>
<items>item7</items>
</div>
<div class="even">
<items>item2</items>
<items>item4</items>
<items>item6</items>
<items>item8</items>
</div>
With this custom ListView class:
class ListViewOdd extends ListView
{
public function renderItems()
{
$models = $this->dataProvider->getModels();
$keys = $this->dataProvider->getKeys();
$rowsOdd = $rowsEven = [];
foreach (array_values($models) as $index => $model) {
if ($index%2 == 0) {
$rowsOdd[] = $this->renderItem($model, $keys[$index], $index);
} else {
$rowsEven[] = $this->renderItem($model, $keys[$index], $index);
}
}
return '<div class="odd">'.implode($this->separator, $rowsOdd) . '</div><div class="even">'.implode($this->separator, $rowsOdd) .'</div>'; // replace <div> to Html::tag('div', ...)
}
}
echo ListViewOdd::widget([
'dataProvider' => $dataProvider,
'itemView' => '_post',
]);
But load more pagination not splitting data again into odd/even listing as my first data list.
i am not passing anything from controller and action i am using model to get data provider
<?php echo ListViewOdd::widget([
'dataProvider' => Posts::getCommonListData($industry,'user','engage',0),
'itemOptions' => ['class' => 'item post-item'],
'summary' => '',
'id' => 'my-listview-id',
'itemView' => '_Posts',
'viewParams' => [
'fullView' => true,
],
'pager' => [
'class' => \app\vendor\kop\y2sp\ScrollPager::className(),
//'negativeMargin' => '200',
'triggerText' => 'Load More',
//'triggerOffset' => 3,
'noneLeftText' => '',
],
]);
getting output like this
<div class="odd">
<items>item1</items>
<items>item3</items>
<items>item5</items>
<items>item7</items>
</div>
<div class="even">
<items>item2</items>
<items>item4</items>
<items>item6</items>
<items>item8</items>
<items>item9</items>
<items>item10</items>
<items>item11</items>
<items>item12</items>
</div>
after clicking loadmore its just loading all records inside even div and load more aoption also coming under even div
Change in method renderItems:
return '<div class="odd">'.implode($this->separator, $rowsOdd) . '</div><div class="even">'.implode($this->separator, $rowsEven) .'</div>';
Mistake is ''.implode($this->separator, $rowsOdd) .''.
Div is even, but data from $rowsOdd :)
I have a Kendo UI datepicker with placeholder data. Here is the HTML:
<input type="text" class="datepicker"' placeholder="yyyy-mm-dd" />
Here is the JavaScript:
var start = $(".datepicker").kendoDatePicker({
format: "yyyy-MM-dd",
parseFormats: ["MM/dd/yyyy"],
change: startChange
}).data("kendoDatePicker");
The Kendo UI datepicker displays the placeholder data in the same style as user entered data. I would like to style the placeholder data differently. Specifically, I would like the text to be gray and italicized. When user enters data, the style changes to solid black (non-italicized). Any thoughts on how to do this?
Well, placeholder is an HTML5 attibute and isn't specic to Kendo controls. As I understand it Kendo doesn't offer any support for placeholder over what is supported by the browser, and remember that only some browsers support this attribute; IE does not.
Anyway, to style the placeholder you'll have to use vendor prefix CSS properties, see here.
I use this..it will work on your HTML and you can style it too :)
<script>
// This adds 'placeholder' to the items listed in the jQuery .support object.
jQuery(function() {
jQuery.support.placeholder = false;
test = document.createElement('input');
if('placeholder' in test) jQuery.support.placeholder = true;
});
// This adds placeholder support to browsers that wouldn't otherwise support it.
$(function() {
if(!$.support.placeholder) {
var active = document.activeElement;
$(':text').focus(function () {
if ($(this).attr('placeholder') != '' && $(this).val() == $(this).attr('placeholder')) {
$(this).val('').removeClass('hasPlaceholder');
}
}).blur(function () {
if ($(this).attr('placeholder') != '' && ($(this).val() == '' || $(this).val() == $(this).attr('placeholder'))) {
$(this).val($(this).attr('placeholder')).addClass('hasPlaceholder');
}
});
$(':text').blur();
$(active).focus();
$('form:eq(0)').submit(function () {
$(':text.hasPlaceholder').val('');
});
}
});
</script>
I am using the tooltipDialog from extlib and want to position the tooltip to the left and right instead of the default which seem to be below.
any idea how to do this?
== Update ==
Found the following code in extlib
eclipse\plugins\com.ibm.xsp.extlib.controls\resources\web\extlib\dijit\TooltipDialog.js
so I tried a few different options, but could not get it to work
http://dojo-toolkit.33424.n3.nabble.com/dijit-TooltipDialog-orientation-of-popup-td1007523.html
XSP.openTooltipDialog("#{id:tooltipDialog1}","#{id:link2}","orient:{BR:'BL',BL:'BR'}")
XSP.openTooltipDialog("#{id:tooltipDialog1}","#{id:link2}","orient:[BR:'BL',BL:'BR']")
XSP.openTooltipDialog = function xe_otd(dialogId,_for,options,params) {
dojo.addOnLoad(function(){
var created = false
var dlg = dijit.byId(dialogId)
if(!dlg) {
options = dojo.mixin({dojoType:"extlib.dijit.TooltipDialog"},options)
dojo.parser.instantiate([dojo.byId(dialogId)],options);
dlg = dijit.byId(dialogId)
created = true;
} else {
if(dlg.keepComponents) {
dijit.popup.open({
popup: dlg,
around: dojo.byId(_for)
});
return;
}
}
if(created) {
dojo.connect(dlg, 'onBlur', function(){
dijit.popup.close(dlg);
})
}
dlg.attr("content", "<div id='"+dialogId+":_content'></div>");
var onComplete = function() {
dijit.popup.open({
popup: dlg,
around: dojo.byId(_for)
});
dlg.focus();
}
var axOptions = {
"params": dojo.mixin({'$$showdialog':true,'$$created':created},params),
"onComplete": onComplete,
"formId": dialogId
}
XSP.partialRefreshGet(dialogId+":_content",axOptions)
})
}
btw: I also need to set the showDelay
also found these usefull links
http://dojotoolkit.org/api/1.6/dijit/TooltipDialog
I think you need to set the following dojo attribute:
<xp:dojoAttribute name="data-dojo-props" value="position:['before']">
</xp:dojoAttribute>
Atleast in dojo-1.8.1,
dijit.popup.open({
popup: dlg,
around: node,
orient: ["after-centered"]
});
places the ToolTipDialog to right of node.
The "position" attribute of the tooltip control supports values of "above", "below", "left", and "right".