I have a following problem, which I am not sure, how to solve. I am building app's setting, where user can specify list of accounts (left TableViewConstoller). As you can see on the screen, there is a Save button, which stores new account into the database.
Everything works, except for empty Name value, which cause an exception. I need to solve it in way, where Save button would be enabled only if data pass validation (Name is not empty).
I was thinking about some event, which would monitor Account.Name property and based on it's value, Save button would be enabled/disabled.
Problem is, that I have no idea, how to achieve that.
Thanks for any suggestions.
For the data to pass validation it would need an event to be triggered first, so why don't you simply hook into the touchupinside event of the 'save' button perform some validation against the data that is being submitted and if it fails display an alert to the user? Seems like a cleaner approach to me, which would also include visual prompting. otherwise you would need the button to be set to disabled from the start and then perform a check every time one of the tableviewcells is interacted with.
The validation would be fairly simple: (obviously use an '&&' operand to validate against more than one empty textbox)
If(nameTextBox.Text.Trim().Length != 0)
{
// Great store the data
}
else
{
UIAlertView alert = new UIAlertView () {
Title = "alert title", Message = "this is a simple alert"
};
alert.AddButton("OK");
alert.Show ();
}
If you have a code example I may be able to be more specific.
Edit:
It's also worth considering your future requirements, should you be able to handle no name being passed, if the user doesn't have one already stored should you force them to supply one, or if the user already has a name and passes through no name change, should you simply keep the existing name and proceed to update all of the other fields that the user may have interacted with. It always pays to take some time to architect out your requirements for any given feature.
Related
In OOB asset form save button is not there, but it is present in my instance.I want to hide this save button.As you can see there are many UI actions, how I can determine which one works an asset table?(all ui actions are on global table)
Please help me out....
As you have correctly pointed out, there are 4 global UI Actions with the name "Save". They all have different combinations of the true/false fields: "Form Button", "Form Context Menu", and "Show Insert".
You want to de-activate the one that has "Form Button" value of "True" and "Show Insert" value "true".
The only reason it is being displayed is because of the condition isAdvancedUI() is returning as true. This is because the system property 'glide.ui.advanced' has been set to true. By setting this to true, a number of useful options in the context menus, become visible as form buttons (Save, Insert, Insert and Stay). Unfortunately one of the save buttons that appears, is not very desirable, because there is already a "submit" for inserting new records.
This is why it is perfectly OK to disable this button globally.
Gordon's answer here (https://community.servicenow.com/thread/261454) is exactly what you're looking for. Identify and override the save buttons (ones with "form button" checked) and you'll be good to go.
Side note: Generally it's a good idea to avoid changing the out-of-box UI actions, especially for something simple like hiding the button. Using a method like adding a condition can result in you 'owning' the button and make upgrades more time consuming. That said, there is a mechanism called 'UI Action Visiblity' that can control visibility for views without modifying (and owning) the UI Action itself. I've used this in the past and it works well.
https://docs.servicenow.com/bundle/istanbul-servicenow-platform/page/administer/list-administration/concept/c_ControllingVisibilityWithRoles.html
You can accomplish this with a Client Script. Keep in mind that hiding the button is obfuscating the Save button rather than restricting the access.
I tested this on a personal instance and it worked.
Name: Hide save button
Table: Asset [alm_asset]
UI Type: Both
Type: onLoad
Active: Checked
Inherited: Checked
Global: Checked
Script
function onLoad() {
var items = $$('BUTTON').each(function(item){
if(item.innerHTML.indexOf('Save') > -1){
item.hide();
}
});
}
This will load when any form view loads that extends the Asset [alm_asset] table because the Inherited box is checked. This is important because you can have hardware assets, license assets, and so on.
When this runs, it will search each button for Save and then hide it if matched.
On an EWF page, is it possible to alter the content of a form item during validation (when a validation fails)? For an example: say you have a text box that you want to be spell checked before it gets entered into the database. You use the modification's GetSpellCheckedWordTextFormItem to get the form item, and you want to replace what the user enters ("teh") with a likely suggestion ("the") when the validation fails to find a word it knows. Then the user sees the validation error ("Is this the word you meant?"), looks at it and corrects it or not, then re-submits.
Is there a way to do that? If so, how?
The specific answer to your question is no, you can't alter any form values if validation fails. To implement this, you'd need to let the validation succeed and let the data get modified. As part of the validation/modification, you could set a piece of page state that causes the next loadData pass to display the "is this the word you meant?" message near the spell-checked form item. Of course, you would have already saved the corrected text.
Alternatively, you could use PostBack.CreateIntermediate to make a post-back that only runs the spell-check, puts the corrected text in page state, and displays "is this the word you meant?". You'd set that post-back to fire when the user tabs out of the text box, and then you'd have the main post-back grab the corrected text from page state and save it in the database or other durable storage.
I want to create a dynamic action, that will set a value to an item on the page, when the value of another item (autocomplete text field) is set.
So the proccess goes like this:
Click on the autocomplete field
type some letters
choose one of the suggested values
I cannot find an event that will be executed when the selection of one of the suggested values happens. This way, I cannot see how I can read the value of the autocomplete field, once a suggested value is selected.
The change event doesn't fit my needs, it doesn't execute when one suggested value is selected.
I had the same problem, found this link: https://community.oracle.com/thread/2130716?tstart=0 and modified my dynamic action as follows to get the desired behaviour:
Event = Custom
Custom Event = result
From the link:
the problem seems to be the default behavior of the browser. When you
enter some text into the autocomplete and the list is displayed, the
focus is still in the text field. Also if you use the keyboard cursors
to pick an entry the focus will still be in the textfield. That's why
the change event of the textfield doesn't fire. It only fires if you
leave the field.
On the other side if you pick an entry with the mouse, the browser
will remove the focus from the text field for a moment (before the
JavaScript code puts the focus back), because you clicked outside of
the field. But that's enough so that the browser fires the change
event.
I had a look into documentation of the underlaying jQuery Autocomplete
widget
(http://bassistance.de/jquery-plugins/jquery-plugin-autocomplete/) and
there is actually an event called "result" which can be captures if an
entry is selected from the drop down list.
Try "Lose Focus" as event. It will trigger your dynamic action when you leave the autocomplete field, i.e. your curosr is moved to another field.
This probably depends on the APEX version you are using.
In case of 18.2, because the underlying component is based on Oracle JET's "inputSearch" component, you need to use following configure to capture the select change event for text with autocomplete:
event: Custom
custom event: ojupdate
Reference:
https://docs.oracle.com/cd/E87657_01/jet/reference-jet/oj.ojInputSearch.html#event:optionChange
I turned on the browser console, then turned ApEx Developer toolbar debug, and found that, on the contrary, the "Change" event does fire upon user clicking with the mouse on one of the selections. However if the user uses keyboard (type a few letters to narrow the list down, then use down arrow key to arrive at desired value, then press enter) then the Change event does not fire, just as you say.
Moreover: even when you do get the value sent back via mouse-click initiated Change event, the value isn't the autocomplete's complete and valid value, but instead the possibly partial and wrong-case value just as typed by the user. I.e., the the change event's submission of the value precedes the autocomplete's substitution.
The answer that #VincentDeelen gave is the best alternative that I can see, although it doesn't quite give that "instantantenous synchronicity" feel. You could maybe use the "Key Down" event, but be careful with that. You could get a really excessive amount of web and db traffic as each and every keystroke (including corrections) results in another firing of the dynamic action.
Testing environment: ApEx 4.2.3 with Chrome 33 as well as IE 9.
p.s. This might be worth a mention to the ApEx development team as well.
It's not really ideal, but you could use onfocus(). I'm looking for the same thing you are, I think, a custom event that fires when the selection of a suggested value happens. I haven't found it yet though and that is my work-around for now. It will run whatever function you've created for this initially with no value, but once the selection is made it will return focus and run the function again with the right value. Like I said, not ideal but it works.
Jeffrey Kemp is right. You can set it up through a dynamic action using the custom event, result. You can also register it on page load using document.getElementById("{id}").addEventListener("result", {function}); or $("#{id}").result( function( event, data, formatted ) { //something here });.
Oracle apex 19 now added a "component event" when you create a dynamic action called "Update [Text Field with autocomplete]" - this action is fired when you select a value from the list, but not when you leave the field (similar to adding the custom event "ojupdate").
I have a basic model :
class MyModel(models.Model):
my_field = models.CharField()
I have a basic form for this model :
class MyFrom(forms.ModelForm):
class Meta:
model = MyModel
And I have a function that does a basic lookup (a lot more complex in reality, regex etc. won't do) :
POSSIBLE_VALUES = ['aa', 'bb', 'cc', 'dd']
def lookup(some_value):
if some_value in POSSIBLE_VALUES:
# the value is OK, return a string
return some_value
else:
# constructs the 'did you mean' list of suggestions
didyoumean = [pv for pv in POSSIBLE_VALUES if pv in some_value]
# returns a list which might be empty
return didyoumean
Now, the scenario that I want is:
On the site I enter a value in the "my_field" input field and hit submit button.
If the value passes the lookup I should automatically perform the form's action.
If I get multiple possible values then I should display them to the user and no other action is performed.
If I get no answers (an empty list) I should get an error message.
Some additional requirements:
I would prefer the "did you mean" list to be displayed without having to reload the page.
If a user clicks on one of the suggestions I want to perform the form's action without an additional lookup - the value has already been checked.
I want to keep all the logic outside the view and keep it in the form or in the model. This is a must.
I want to avoid hardcoded js in the template and push it into the form if possible. It's not a must.
So I assume that it would all be distributed between this fields validation and a custom widget that would handle the "did you mean" list rendering. I just can't put it all together.
Your help is required :)
EDIT. Ad. 2 in requirements.
That is a basic feature I described. In a more advanced one I want this form to have more fields and so the "did you mean" list should be displayed along with all other fields errors (if any). Then clicking on a hint would just set the my_field's value to it's value without reloading the form. A user would have to correct other errors as well so I can't go to form's action right away. Might there be just some some flag to switch between those two options ("basic" and "advanced").
I would prefer the "did you mean" list to be displayed without
having to reload the page.
Create custom widget, which renders with JS code for checking possible values as user enters it
If a user clicks on one of the suggestions I want to perform the
form's action without an additional
lookup - the value has already been
checked.
Again, that widget, when clicked, should just submit the form.
I want to keep all the logic outside the view and keep it in the
form or in the model. This is a must.
On the form you'll have clean() method to validate everything. If, say, some bogus data passes with submit from p. 2 - you still raise validation error.
I want to avoid hardcoded js in the template and push it into the form if
possible. It's not a must.
Solved with custom widget, details.
I'd like to ask your opinion on this. This is a theoretical question.
I'm in a situation where I have an interface shown to a user that uses AJAX to talk to the server. The server-side language does not matter here. I have a form with fields and each of them are deletable. If the user selects a few "delete" -checkboxes and presses Update, then I have these two options to do:
Option 1:
When deleting fields, use JavaScript to remove the HTML immediately and run AJAX on background to delete those fields. This achieves a look of a fast interface -> better user experience. However, if the AJAX call fails on the server side (the fields couldn't be deleted), then the previously deleted HTML fields would give a false assumption for the user (of them being deleted).
Option 2:
When deleting fields, run AJAX, depending on its success, either remove the HTML or do not. This gives accurate feedback for the user, but the form would freeze until the AJAX call finishes = slow(er).
What are your thoughts? Which approach seems better for me to take or should I make it an option?
Option 3: Mark the controls as being deleted (e.g. overlay a translucent gray box with a delete icon on it). Send the request. When it returns, either remove the controls, or change the box to show an error icon for a few seconds (then remove the box).
Allow the rest of the interface to be interacted with while this goes on.
Nice question.
A third option would be to :
disable immediately the controls
delete them when the Ajax returns
This gives the user feedback that something was effectively requested (responsiveness),
while showing also the moment where it is effectively completed.
Also, the user somehow feels the "distant call", which does not induce him in error, because it is was really happens. Anyway, there is nothing meaningful we can do to hide this feeling, because the delay will always be there.