NativeScript TextField canPerformActionWithSender - nativescript

I have a custom keyboard (made from buttons) in my app and I'm using it to populate a numeric value into a TextField. When a button is pressed, I set the text of the TextField while sanitizing the data — making sure there's only 1 decimal, no letters are entered, etc.
However, I'm now trying to detect when a user attempts to paste into the field so I can either prevent it entirely or sanitize the pasted text before allowing it to be pasted.
The approach I've taken so far is to try to implement the canPerformActionWithSender method on a NativeScript TextField.
I've tried the following (I'm using NativeScript Vue):
<TextField
ref="amount"
hint="$0.00"
#loaded="onTextFieldLoaded"
#unloaded="onTextFieldUnloaded" />
And...
onTextFieldLoaded(event) {
let textField = event.object
textField.focus()
nativeView.canPerformActionWithSender = (action, sender) => {
// `action` may be 'paste' so I can handle that action here
}
}
But this doesn't work. Is there an easy way to accomplish this without creating a custom component?

I was able to solve this with the following:
UITextField.prototype.canPerformActionWithSender = function (action, sender) {
return false;
}
This will disable the copy/paste/etc. menu completely. You can be more specific and check the action to only disable certain functionality if you like.
UITextField.prototype.canPerformActionWithSender = function (action, sender) {
if (action == 'paste:') {
return false;
}
return true;
}

Related

Xamarin, how can I gain a completed state from a command?

I have a ListView and am using the SelectedItem to call a command and show a modal view.
However, I have an issue where the user can tap multiple times on the listview row and multiple modal views are shown before the view has loaded. Granted this only happens on slower devices.
This is is caused because the command doesn't have any call back.
I wouldn't normally paste code here, but in this case I thought it was more descriptive to provide a screen shot.
I've looked into the AsyncCommands but these seem to be used more to handle errors.
I'm currently thinking about a subscribe approach which is triggered when the modal is exited, however I think there must be another way I haven't thought of.
Can you try using a Boolean as IsSelected & make IsSelected true when user clicks an item from list & change your condition in setter as below. When your operations are done reset the flag.
This was, there wont not be any duplication of modals. This is what I understood from your question, if there's something else, please let me know.
if( _locationAssetSelected || !IsSelected )
{
IsSelected = true;
_locationAssetSelected = value;
..... //your code
_locationAssetSelected = null;
IsSelected = false;
}
You could move the logic to the command to make sure it doesn't execute multiple times. This is a snippet on the sample/template Forms app which uses this method as a command. Lock seems unnecessary.
async void OnItemSelected(Item item)
{
//lock (selectLock)
//{
if (item == null || selectionOn)
return;
selectionOn = true;
//}
System.Diagnostics.Debug.WriteLine($"{item.Text} selected");
// This will push the ItemDetailPage onto the navigation stack
await Shell.Current.GoToAsync($"{nameof(ItemDetailPage)}?{nameof(ItemDetailViewModel.ItemId)}={item.Id}");
selectionOn = false;
}

Custom Cell Format ListView TornadoFx on delete item

I'm new to TornadoFx but am trying it out (also new to JavaFX by extension).
I have a listview defined as so:
private var colorList = mutableListOf<Color>
//other things in init block
colorpicker(mode = ColorPickerMode.MenuButton) {
valueProperty().onChange {
if (it != null) {
colorList.add(it)
}
}
}(Color.BLACK,Color.WHITE).observable()
listview(colorList) {
cellFormat {
text = it.toString()
style {
baseColor = it
}
}
contextmenu {
item("Delete").action {
if (selectedItem != null) {
colorList.remove(selectedItem)
}
}
}
}
//continue init block
Adding and taking away colors from the listview works just fine but the color inside the cell does not disapear if it is no longer occupied
Example of what is happening
The cellFormat function allows you to configure the list cell for each item in your list.
However, when there is no list item for a certain row, the callback is not run, so that you have no way of applying a style to an empty row using the cellFormat approach. One solution would be to implement your own ListCell and always clearing the style property of the cell, but I believe this might actually be fixed within the framework by always clearing the style property before a cell is reused. I just tried to make this change in the framework, and it fixes the issue with your code sample.
I will commit the change now, please try it out with tornadofx-1.7.17-SNAPSHOT :)

How to disable Save Handler on Jqgrid while doing editing

I am working on an ASP.net MVC 4.0 application with Jqgrid.
I am making all rows as editable with some columns being editable and some non editable.
The Problem here is , i dont want to use Save and ESC handlers.
I am saving row details on the blur event of one of the text boxes. and still i need to stay in EDIT Mode.
So, if the user mistakenly presses enter , the row is going out of edit mode.
How to disable these Esc and Save Handlers
Please help..
Updated:
I am not using either cell edit or inline editing or form editing.
I am converting all rows as editable on the loadComplete trigger of the Jqgrid
i have only one Column being editable. that is of type Textbox
So, on the blur event of it , i am saving that to database using an ajax post .
Every thing is working fine upto this.
Here, the grid needs to be in edit mode even after saving value to database.
But, when clciking on enter on that row, it is moving out of edit mode which violates my requirement
I need to stop row moving to View mode from edit mode when ESC or Enter Keys are pressed
I hope this is clear..if not i will mention more..
I Solved it in this way:
Dont know whether it is right way of doing this:
Oleg..i need your views on this:
if(cnt > 0) {
svr.id = rowid; $t.p.savedRow.push(svr);
$(ind).attr("editable","1");
$("td:eq("+focus+") input",ind).focus();
if(o.keys===true) {
$(ind).bind("keydown",function(e) {
if (e.keyCode === 27) {
// debugger
// $($t).jqGrid("restoreRow",rowid, o.afterrestorefunc);
// if($t.p._inlinenav) {
// try {
// $($t).jqGrid('showAddEditButtons');
// }
// catch (eer1) {}
// }
return false;
}
if (e.keyCode === 13) {
// var ta = e.target;
// if(ta.tagName === 'TEXTAREA') { return true; }
// if( $($t).jqGrid("saveRow", rowid, o ) ) {
// if($t.p._inlinenav) {
// try {
// $($t).jqGrid('showAddEditButtons');
// } catch (eer2) {}
// }
// }
return false;
}
});
}
$($t).triggerHandler("jqGridInlineEditRow", [rowid, o]);
if( $.isFunction(o.oneditfunc)) { o.oneditfunc.call($t, rowid); }
}
This is the code , i found in the Jqgrid.src.js
Since, i done need restoreRow and saveRow to be called when Enter key or ESC is pressed, i commented out the code .
I dont know if it is right way to do it. but, this worked indeed for my Scenario.

Slickgrid - One-click checkboxes?

When I create a checkbox column (through use of formatters/editors) in Slickgrid, I've noticed that it takes two clicks to interact with it (one to focus the cell, and one to interact with the checkbox). (Which makes perfect sense)
However, I've noticed that I am able to interact with the checkbox selectors plugin (for selecting multiple rows) with one click. Is there any way I can make ALL of my checkboxes behave this way?
For futher readers I solved this problem by modifing the grid data itself on click event. Setting boolean value to opposite and then the formatter will display clicked or unclicked checkbox.
grid.onClick.subscribe (function (e, args)
{
if ($(e.target).is(':checkbox') && options['editable'])
{
var column = args.grid.getColumns()[args.cell];
if (column['editable'] == false || column['autoEdit'] == false)
return;
data[args.row][column.field] = !data[args.row][column.field];
}
});
function CheckboxFormatter (row, cell, value, columnDef, dataContext)
{
if (value)
return '<input type="checkbox" name="" value="'+ value +'" checked />';
else
return '<input type="checkbox" name="" value="' + value + '" />';
}
Hope it helps.
The way I have done it is pretty straight forward.
First step is you have to disable the editor handler for your checkbox.
In my project it looks something like this. I have a slickgridhelper.js to register plugins and work with them.
function attachPluginsToColumns(columns) {
$.each(columns, function (index, column) {
if (column.mandatory) {
column.validator = requiredFieldValidator;
}
if (column.editable) {
if (column.type == "text" && column.autocomplete) {
column.editor = Slick.Editors.Auto;
}
else if (column.type == "checkbox") {
//Editor has been diasbled.
//column.editor = Slick.Editors.Checkbox;
column.formatter = Slick.Formatters.Checkmark;
}
}
});
Next step is to register an onClick event handler in your custom js page which you are developing.
grid.onClick.subscribe(function (e, args) {
var row = args.grid.getData().getItems()[args.row];
var column = args.grid.getColumns()[args.cell];
if (column.editable && column.type == "checkbox") {
row[column.field] = !row[column.field];
refreshGrid(grid);
}
});
Now a single click is suffice to change the value of your checkbox and persist it.
Register a handler for the "onClick" event and make the changes to the data there.
See http://mleibman.github.com/SlickGrid/examples/example7-events.html
grid.onClick.subscribe(function(e, args) {
var checkbox = $(e.target);
// do stuff
});
The only way I found solving it is by editing the slick.checkboxselectcolumn.js plugin. I liked the subscribe method, but it haven't attached to me any listener to the radio buttons.
So what I did is to edit the functions handleClick(e, args) & handleHeaderClick(e, args).
I added function calls, and in my js file I just did what I wanted with it.
function handleClick(e, args) {
if (_grid.getColumns()[args.cell].id === _options.columnId && $(e.target).is(":checkbox")) {
......
//my custom line
callCustonCheckboxListener();
......
}
}
function handleHeaderClick(e, args) {
if (args.column.id == _options.columnId && $(e.target).is(":checkbox")) {
...
var isETargetChecked = $(e.target).is(":checked");
if (isETargetChecked) {
...
callCustonHeaderToggler(isETargetChecked);
} else {
...
callCustonHeaderToggler(isETargetChecked);
}
...
}
}
Code
pastebin.com/22snHdrw
Search for my username in the comments
I used the onBeforeEditCell event to achieve this for my boolean field 'can_transmit'
Basically capture an edit cell click on the column you want, make the change yourself, then return false to stop the cell edit event.
grid.onBeforeEditCell.subscribe(function(row, cell) {
if (grid.getColumns()[cell.cell].id == 'can_transmit') {
if (data[cell.row].can_transmit) {
data[cell.row].can_transmit = false;
}
else {
data[cell.row].can_transmit = true;
}
grid.updateRow(cell.row);
grid.invalidate();
return false;
}
This works for me. However, if you're using the DataView feature (e.g. filtering), there's additional work to update the dataview with this change. I haven't figured out how to do that yet...
I managed to get a single click editor working rather hackishly with DataView by calling
setTimeout(function(){ $("theCheckBox").click(); },0);
in my CheckBoxCellEditor function, and calling Slick.GlobalEditorLock.commitCurrentEdit(); when the CheckBoxCellEditor created checkbox is clicked (by that setTimeout).
The problem is that the CheckBoxCellFormatter checkbox is clicked, then that event spawns the CheckBoxCellEditor code, which replaces the checkbox with a new one. If you simply call jquery's .click() on that selector, you'll fire the CheckBoxCellEditor event again due because slickgrid hasn't unbound the handler that got you there in the first place. The setTimeout fires the click after that handler is removed (I was worried about timing issues, but I was unable to produce any in any browser).
Sorry I couldn't provide any example code, the code I have is to implementation specific to be useful as a general solution.

how to dismiss the dropdown list of an autocompletebox in windows phone 7

is there anyway to programmatically dismiss the drop-down list of an autocompletebox? my use case is as follows.
MainPage.xaml passes a value to SearchPage.xaml (i.e. /SearchPage.xaml?query=someText).
in SearchPage.xaml.cs, i set,
autoCompleteBox.Text = NavigationContext.QueryString["query"].
at this point, the drop-down list of suggested matches shows up. i don't want this behavior when the page is just navigated to.
i also tried the following to dismiss the drop-down list but it didn't help.
autoCompleteBox.Text = NavigationContext.QueryString["query"];
autoCompleteBox.IsDropDownOpen = false;
the drop-down list seems to go away from the AutoCompleteBox when it loses focuses, but i don't see a property/field to set to make it lose focus.
any help is appreciated.
well, i tinkered a bit and came up with a kludge. in the constructor of SearchPage.xaml.cs i have the following code.
autoCompleteBox.TextFilter += DummyFilter;
autoCompleteBox.GotFocus += (s,args) => {
if(!isAutoCompleteBoxInit) {
autoCompleteBox.TextFilter -= DummyFilter;
autoCompleteBox.TextFilter += RealFilter;
}
}
DummyFilter looks like the following.
bool DummyFilter(string search, string value) { return false; }
RealFilter looks like the following.
bool RealFilter(string search, string value) {
if(null != value) return value.ToLower().StartsWith(search.ToLower());
}
in my OnNavigatedTo method, is where i set, autoCompleteBox.Text = NavigationContext.QueryString["query"]. so when i do this now, the DummyFilter will always return false, so the drop-down list goes away. when the user focuses in on the AutoCompleteBox, i check if the correct Filter was already attached to the TextFilter property, if not, then i do a switch.
hope this helps some of you.
Is there any other focusable control on the page? Just set the focus somewhere else, and your problem should be solved.
When you have changed the text of the AutoCompleteBox the dropdown will open. Only when the user has changed the text and there is a match then the dropdown will close.
Just change userInitiated to true and when there is a match the dropdown will close.
private void UpdateTextCompletion(bool userInitiated)
{
userInitiated = true; ...

Resources