UI5: Validate Whole Form's Required and Visible Fields for Null/Blank Values - forms

onPress of submit button, I want to validate all SimpleForms' fields (ComboBox, Input, DatePicker, etc.) that are
required &
visible
to see if they are null or blank (""). If a targeted (required & visible) field is null/blank, set that control's state to "Error" and display an error message. If no targeted field is null/blank, pop up a success dialog box.

This method is automated so in the future, any fields added later will automatically be checked without need of manual additions to controller code.
Controller code:
requiredAndVisible: function(oControl) {
if (typeof oControl.getRequired === "function") { //certain ctrls like toolbars dont have getRequired as a method, so we want to skim those out, else itll throw an error later in the next check
if (oControl.getRequired() === true && oControl.getVisible() === true) {
return oControl;
}
}
},
onSubmit: function() {
var valid = true,
oView = this.getView(),
aFormInitial = oView.byId("formInitial").getContent(), // get all the controls of SimpleForm1
aFormConfig = oView.byId("formConfiguration").getContent(), // get all controls of SimpleForm2
aControls = aFormInitial.concat(aFormConfig), // combine the 2arrays together into 1
aFilteredControls = aControls.filter(this.requiredAndVisible); // check each element if it required & visible using the 1st function. return only the controls that are both req'd & visible
aFilteredControls.forEach(function(oControl) { // in resultant array, check each element if...
if (!oControl.getValue() || oControl.getValue().length < 1) { // its value is null or blank
oControl.setValueState("Error");
valid = false; // set valid to false if it is
} else {
oControl.setValueState("None");
}
});
if (valid === false) {
// **replace this code with w/e error handling code u want**
oView.byId("errorMsgStrip").setVisible(true);
} else if (valid === true) {
// **replace this code with whatever success handling code u want**
var oDialogConfirm = new sap.ui.xmlfragment("dialogID", "dialog.address.here", this);
oDialogConfirm.open();
}
},

Related

How can i get the initial context path in my custom sapui5 control?

i have designed my own custom sapui5 control. This control is also used as a template in a 'sap.ui.table' control. This table contains 5 rows and is bound to an odata result set with mostly more than 5 rows. So when i now scroll through this table, i have to adapt my control to the new bound value. But the value of this control can also be changed due to propertybinding by an other control of the same table row because of an dependency between the values of bound data of that row.
So i have to recognize, if a value change in the control is issued by a "normal" property setting by a change method of another control in the same row, or if it is issued by a table scroll operation.
For this i check the contextpath of the bound value in the setter of my control. if the context path is different from my stored last context path, the change is issued by a table scroll operation. If the context is unchanged, it is issued by another programmatically operation (maybee the change-event of another control in the same table row which has a dependency to this control).
For this i store the context-path in an internal instance variable of my control. But the problem is the initial value. How can i save the inital, first bound context path, in my control. It is not possible and allowed to check this in the constructor of my control. And initially a scroll and and a programmtic change would return a context change.
Here a simplified code snippet of my control for better understanding. Because of the simplyfing excuse for syntax errors.
sap.ui.define(["sap/ui/core/Control",
"sap/ui/model/Filter",
"sap/ui/model/FilterOperator"
], function (Control, Filter, FilterOperator) {
"use strict";
return Control.extend("MyControl", {
"metadata": {
"properties": {
"value" : { type : "string" }
}
},
init: function () {
this._lastContextPath = ""; // should store the last context path
},
setValue : function(oValue) {
// Setter Method for my value Property
this.setProperty("value1",oValue);
// Check if setter was issued by scrolling if this control
// is bound to a table
if (this.getId().indexOf("clone") > 0) // Simplified recognition if control is created by template
if ( !this._hasContextChanged() ) {
// Do something in the parent-control where this Control is in its aggregation
// because Context not changed, so Setter is issued programmtically
if (typeof this.getParent() !== 'undefined' && this.getParent() !== null) {
// In this case the Parent-Method refreshFromChild should be invoke with the
// value of this control
this.getParent.refreshFromChild(oValue);
}
}
}
},
// Checks if a context change has happend
_hasContextChanged : function() {
var oBinding = this.getBinding("value");
if ( typeof oBinding !== 'undefined' && oBinding !== null) {
if (this.getId().indexOf("clone")>0) { // Simplified recognition if control is created by template
var oContext = oBinding.getContext();
var sContextPath = oContext.sPath;
if (sContextPath !== this._lastContextPath ) {
// Context changed. Normally by a table scroll operation
this._lastContextPath = sContextPath;
return true;
}
else {
return false;
}
}
else {
return false;
}
}
else {
return false;
}
}
})
)

Show confirmation box in dhtmlx scheduler onbeforeviewchange

I want to show the confirmation box before view change. So when user change date for scheduler I want to show confirmation box whether user want to redirect to another date or not.
The simplest solution would be to use window.confirm
It pauses code execution until user choses any option, so you can use simple if-else statement:
scheduler.attachEvent("onBeforeViewChange", function (oldMode, oldDate, mode, date) {
if (oldMode && oldDate) {
if (oldMode !== mode || oldDate.valueOf() !== date.valueOf()) {
if (confirm("are you sure?")) {
return true;
}
return false;
}
}
return true;
});
demo: https://snippet.dhtmlx.com/140d2ff31
If you want a custom confirmation popup, which doesn't block the browser, you'll need to do a small workaround, since scheduler API doesn't support async event handlers:
1) when code enters onBeforeViewChange, you display the dialog and always return false from the handler in order to keep the same date
2) when the user confirms view change - you set some flag to temporary disable step 1 and call scheduler.setCurrentView from the callback. onBeforeViewChange runs again, you check the flag you've set and return true this time, allowing date change.
var callbackViewChange = false;
scheduler.attachEvent("onBeforeViewChange", function (oldMode, oldDate, mode, date) {
if (oldMode && oldDate) {
//
if (!callbackViewChange && (oldMode !== mode || oldDate.valueOf() !== date.valueOf())) {
dhtmlx.confirm({
text: "are you sure?",
callback: function (result) {
if (result) {
// set the flag in order to allow view change
callbackViewChange = true;
scheduler.setCurrentView(date, mode);
callbackViewChange = false;
}
}
});
// cancel view change while we wait for user action
return false;
}
}
return true;
});
demo: https://snippet.dhtmlx.com/a2b8b09b9

How to trigger selected option event?

I am trying to write some Javascript (not Jquery) that when the address dropdown field is clicked it will trigger an event to check the value in the 'ship state' field.
<script>
var addressDropdown = document.querySelector('#address-id');
var shipstateDropdown = document.querySelector('#shipstate-id');
var SelectedShipState;
addressDropdown.addEventListener('click', (addressEvent) => {
if (shipstateDropdown.options[shipstateDropdown.selectedIndex].value === "CA") {
SelectedShipState = "CA";
RunRule();
}
})
</script>
I resolved my issue. I first had to set the event handler for the address drop down which when this occurred it triggered a function. That function then gets the value from the ship state dropdown.
I also added in a setTimeout because the act of triggering the address handler was grabbing the ship state before the value could arrive resulting in a value that was delayed or null.
// Global defined variables //
var SelectedShipState
var selectElement = document.getElementById('ship-state-id');
var addressBook = document.getElementById('address-book-id');
// Change Event: When an address from the address book is selected ...
addressBook.addEventListener('change', (addressEvent) => {
// ... run this function to get the ship state.
setTimeout(addressFunction, 1000);
})
// When this function runs ...
function addressFunction() {
// ... get the value from the ship state select option.
SelectedShipState = this.selectElement.options[selectElement.selectedIndex].value;
RunRule();
}
// Change Event : Get the option each time it is selected //
selectElement.addEventListener('change', (changeEvent) => {
SelectedShipState = `${changeEvent.target.value}`;
RunRule();
})
function RunRule () {
// do something ...
}

Event.stop within .each (prototype)

I am struggling with function that should check form fields before submitting.
I have some select (dropdown fields) and a text field. None of them should be empty for submit.
The script http://jsfiddle.net/6KY5J/2/ to reproduce.
I check dropdown fields within .each and additional text field. Here is the function:
function checkFields(e) {
$$('.dropdown').each(function (element) {
if (element.selectedIndex === 0) {
alert('Fill all dropdown fields!');
Event.stop(e);
throw $break;
return;
}
});
if ($('sometext').value == '') {
alert('Fill the input!');
Event.stop(e);
return;
}
alert('OK!');
}
But I am not able to prevent further execution of the script if one of dropdown is empty. Event.stop(e) seems to to work for the input field only in the second part.
Desired behaviour:
Check dropdowns, if one is empty, stop execution, do not make any
further checks.
Check text input field only if dropdowns are not empty.
Submit only if everything if filled.
The issue is in step 1. My script does not stop here, alerts, but does not stop. Any idea? Thank you!
function checkFields(e) {
var dropdownsokay = true;
$$('.dropdown').each(function (element) {
if (dropdownsokay && element.selectedIndex === 0) {
alert('Fill all dropdown fields!');
Event.stop(e);
dropdownsokay = false;
}
});
if(dropdownsokay) { //only check textfield if all the dropdowns are okay
if ($('sometext').value == '') {
alert('Fill the input!');
Event.stop(e);
return;
}
alert('OK!');
}
}

How to fire place_changed event for Google places auto-complete on Enter key

The click seems to fire the event and set the cookies but pressing enter to submit doesn't set the cookies and instead the page redirects without the cookies.
function locationAuto() {
$('.search-location').focus(function () {
autocomplete = new google.maps.places.Autocomplete(this);
searchbox = this;
google.maps.event.addListener(autocomplete, 'place_changed', function () {
var thisplace = autocomplete.getPlace();
if (thisplace.geometry.location != null) {
$.cookie.raw = true;
$.cookie('location', searchbox.value, { expires: 1 });
$.cookie('geo', thisplace.geometry.location, { expires: 1 });
}
});
});
The .search-location is a class on multiple textboxes.
There is a submit button that takes the values from the cookies and redirects (server side)
Adapted from Jonathan Caulfield's answer:
$('.search-location').keypress(function(e) {
if (e.which == 13) {
google.maps.event.trigger(autocomplete, 'place_changed');
return false;
}
});
I've encountered this problem as well, and came up with a good solution. In my website I wanted to save the autocomplete.getPlace().formatted_address in a hidden input prior to submission. This worked as expected when clicking the form's submit button, but not when pressing the Enter key on the selection in the autocomplete's dropdown menu. My solution was as follows:
$(document).ready(function() {
// Empty the value on page load
$("#formattedAddress").val("");
// variable to indicate whether or not enter has been pressed on the input
var enterPressedInForm = false;
var input = document.getElementById("inputName");
var options = {
componentRestrictions: {country: 'uk'}
};
autocomplete = new google.maps.places.Autocomplete(input, options);
$("#formName").submit(function(e) {
// Only submit the form if information has been stored in our hidden input
return $("#formattedAddress").val().length > 0;
});
$("#inputName").bind("keypress", function(e) {
if(e.keyCode == 13) {
// Note that simply triggering the 'place_changed' event in here would not suffice, as this would just create an object with the name as typed in the input field, and no other information, as that has still not been retrieved at this point.
// We change this variable to indicate that enter has been pressed in our input field
enterPressedInForm = true;
}
});
// This event seems to fire twice when pressing enter on a search result. The first time getPlace() is undefined, and the next time it has the data. This is why the following logic has been added.
google.maps.event.addListener(autocomplete, 'place_changed', function () {
// If getPlace() is not undefined (so if it exists), store the formatted_address (or whatever data is relevant to you) in the hidden input.
if(autocomplete.getPlace() !== undefined) {
$("#formattedAddress").val(autocomplete.getPlace().formatted_address);
}
// If enter has been pressed, submit the form.
if(enterPressedInForm) {
$("#formName").submit();
}
});
});
This solution seems to work well.
Both of the above responses are good answers for the general question of firing a question when the user presses "enter." However - I ran into a more specific problem when using Google Places Autocomplete, which might have been part of the OP's problem. For the place_changed event to do anything useful, the user needs to have selected one of the autocomplete options. If you just trigger 'place_changed', the if () block is skipped and the cookie isn't set.
There's a very good answer to the second part of the question here:
https://stackoverflow.com/a/11703018/1314762
NOTE: amirnissim's answer, not the chosen answer, is the one to use for reasons you'll run into if you have more than one autocomplete input on the same page.
Maybe not the most user friendly solution but you could use JQuery to disable the enter key press.
Something like this...
$('.search-location').keypress(function(e) {
if (e.which == 13) {
return false;
}
});