ValidationError: 'value' is not a valid binding on <textField> elements Svelte-Native - svelte-native

I've created a new Svelte-native application and I'm trying to bind my value as follows:
<script lang="ts">
let newItem = ''
</script>
<page>
<actionBar title="Svelte Native App" />
<flexboxLayout flexDirection="column">
<textField bind:value={newItem} />
</flexboxLayout>
</page>
The problem is, when I run this application I get the following error:
ValidationError: 'value' is not a valid binding on elements
I'm not sure how to solve this, my IDE (VSCode) also returns a svelte invalid binding error.

Related

Depending fields validation

I have two password fields that, among other rules, have to be equal for the form to be valid.
<form onSubmit="resetPassword">
<ValidationGroup valid-bind="$page.formvalid" >
<FlexCol>
<TextField
value-bind="$page.password1"
label="Password 1"
inputType="password"
required
validationRegExp={/(?=.*\d)(?=.*[!##$%^&*]+)(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$/}
minLength="6"
onValidate="validatePasswordsEqual"
/>
<TextField
value-bind="$page.password2"
label="Password 2"
inputType="password"
required
validationRegExp={/(?=.*\d)(?=.*[!##$%^&*]+)(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$/}
minLength="6"
onValidate="validatePasswordsEqual"
/>
<Button
submit
disabled-expr="!{$page.formvalid}"
text="Reset Password"
/>
</FlexCol>
</ValidationGroup>
</form>
However, the validatePasswordsEqual runs only for the currently edited field, leaving the other field always unequal. I tried using store.notify() from inside the validatePasswordsEqual, but without success.
How can I cause validation on both fields at the same time?
You can use the validationParams field to trigger the validation if a value in another field changes.
<TextField
value-bind="$page.password1"
label="Password 1"
inputType="password"
validationParams={{ password2: { bind: '$page.password2 }}
required
validationRegExp={/(?=.*\d)(?=.*[!##$%^&*]+)(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$/}
minLength="6"
onValidate="validatePasswordsEqual"
/>
The third argument provided to the onValidate callback will be the calculated value of validationParams.

How to access TextArea's text and/or change it?

XML View
<TextArea id="message"
maxLength="100"
width="100%"
valueLiveUpdate="true"
showExceededText="false"
placeholder="Type here.."
required="true"
/>
Controller
onInit: function() {
// ...
this.getView().byId("message").setText("");
},
Here I tried two commands to clear the text area values. But got error
this.getView().byId("message").setText("");
TypeError: this.getView(...).byId(...).setText is not a function
sap.ui.getCore().byId("message").setText("");
TypeError: sap.ui.getCore(...).byId(...) is undefined.
How to clear TextArea values from JS?
The control sap.m.TextArea doesn't have the text property and thus no such mutator and accessor either. Instead, the text value can be set via the property value since the control extends InputBase.
Therefore, the line should be:
this.byId("message").setValue();

Validate input of datetime picker

How to register validationError callback for datetimepicker in XML view and how to get this event fired for invalid date input.
The datetimepicker control is an input box with a popup date picker.
The user can type directly into the input or use the date picked to select a date. I can add sophisticated validation to the datetime value but I am trying to simply trigger the validationError event when the user types an invalid date into the box, for example "1010101010010101010101010" or "32/15/2019".
Ideally I am looking for a constraint that tests for a valid date value and triggers the validationError() function if needed.
I guess a workaround is to use the change() event and do the validation in JS, set the valueState etc, but I want to understand what the datetimepicker can do in this regard without having to resort to excess JS.
I am convinced this must be in the docs somewhere but have not yet found anything conclusive. I feel strictParsing should play some part.
I found this SO questionabout setting date range constraints via declaring a new data type. I thought this might be a solution but I am stuck with how to set the constraint for 'a valid date' input value.
Reading the SAPUI5 docs about sap.ui.model.type.DateTime it mentions
The DateTime type supports the following validation constraints:
maximum (expects an dateTime presented in the source-pattern format)
minimum (expects an dateTime presented in the source-pattern format)
which gives no pointers over how to do a straight date validity or format check.
Can anyone point me in the right direction?
EDIT - on suggestion of #Matbtt and reference to docs I altered the type to the string literal sap.ui.model.type.DateTime. However the snippet then produced no output. I traced this to the binding to the model where I was binding to a string. When changed to bind to a JS date object this was fixed.
EDIT - on suggestion of #Developer added validationError callback but does not appear to work. See snippet.
// JSON sample data
var classData = {className: "Coding 101", id: 800, startdate: "2017-12-31T23:59:59.000"}
// convert JSON date to JS date object and format via moment for UI5 consumption
classData.startdateraw = new Date(classData.startdate)
classData.startdatefmt = moment(classData.startdateraw).format('YYYY-MM-DD-HH-mm-ss')
sap.ui.getCore().attachInit(function() {
"use strict";
sap.ui.controller("MyController", {
onInit: function() {
// create JSON model instance
var oModel = new sap.ui.model.json.JSONModel();
// set the data for the model
oModel.setData(classData);
// set model to core.
sap.ui.getCore().setModel(oModel);
// Enable validation !!
sap.ui.getCore().getMessageManager().registerObject(this.getView(), true);
this.getView().byId("startDate").attachValidationError(function(){
alert('Validation error fires - hoorah')
})
},
valError : function(){
console.log("There was a validation error")
}
});
sap.ui.xmlview({
viewContent: jQuery("#myView").html()
}).placeAt("content");
});
<script src="http://cdnjs.cloudflare.com/ajax/libs/moment.js/1.7.2/moment.min.js"></script>
<script src="https://sapui5.hana.ondemand.com/resources/sap-ui-core.js" id="sap-ui-bootstrap" data-sap-ui-theme="sap_bluecrystal" data-sap-ui-libs="sap.m" data-sap-ui-bindingSyntax="complex" data-sap-ui-compatVersion="edge" data-sap-ui-preload="async"></script>
<script id="myView" type="ui5/xmlview">
<mvc:View controllerName="MyController" xmlns="sap.m" xmlns:core="sap.ui.core" xmlns:mvc="sap.ui.core.mvc" xmlns:layout="sap.ui.commons.layout" xmlns:f="sap.ui.layout.form">
<f:SimpleForm id="EditForm" maxContainerCols="2" editable="true" width="25rem" layout="ResponsiveGridLayout" path="{}">
<f:content>
<Label id="lblStartDate" text="Start" design="Bold" labelFor="startDate" />
<DateTimePicker
id="startDate"
placeholder="Enter a crazy date and time, e.g. 23/01/12345"
valueFormat="yyyy-MM-dd-HH-mm-ss"
validationError="valError"
value="{
path: '/startdateraw',
type: 'sap.ui.model.type.DateTime',
strictParsing: 'true'
}"
/>
</f:content>
</f:SimpleForm>
</mvc:View>
</script>
<div id="content"></div>
You can do it by handling change event of sap.m.DateTimePicker:
handleChange : function(oEvent){
var bValid = oEvent.getParameter("valid");
if(!bValid){
sap.m.MessageToast.show("Entered date range isn't valid");
return;
}
}
Jsbin working example.
EDITED 15:03 310117
Change event of sap.m.DateTimePicker is borrowed event from class sap.m.DatePicker.
Resolution
First, we need to distinguish between the events parse error and validation error.
parseError is fired when the user input could not be parsed (e.g. "123123").
validationError is fired only when the input could be parsed but violates one of the constraints defined in the property binding info object.
With the help of type and constraints in property binding, invalid user inputs can be automatically prevented from being stored in the model.
Additionally, you can also register the control or the entire application in the MessageManager for automatically generating the error messages in order to notify and guide the user what to do.
Refer to "Formatting, Parsing, and Validating Data" and "Validation Messages".
Sample
Here are some samples with sap.m.DateTimePicker corresponding to the model:
JSONModel
globalThis.onUI5Init = () => sap.ui.require([
"sap/ui/core/mvc/XMLView",
"sap/ui/model/json/JSONModel",
"sap/ui/core/Core",
], async (XMLView, JSONModel, core) => {
"use strict";
const control = await XMLView.create({
definition: `<mvc:View xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m"
xmlns:core="sap.ui.core"
core:require="{
TypeDateTime: 'sap/ui/model/type/DateTime'
}"
displayBlock="true"
>
<App>
<Page showHeader="false" class="sapUiResponsiveContentPadding">
<ObjectAttribute title="Model value" text="{/myDate}" />
<ObjectAttribute title="Minimum Date" text="today" />
<DateTimePicker id="myDTP"
width="15rem"
value="{
path:'/myDate',
type: 'TypeDateTime',
formatOptions: {
style: 'medium/short'
}
}"
parseError="alert('Parse error')"
validationError="alert('Validation error')"
/>
</Page>
</App>
</mvc:View>`,
afterInit: function() {
const dateTimeValueBinding = this.byId("myDTP").getBinding("value");
dateTimeValueBinding.getType().setConstraints({
minimum: new Date(), // today
});
},
models: new JSONModel({
myDate: new Date(),
}),
});
core.getMessageManager().registerObject(control, true);
control.placeAt("content");
});
<script id="sap-ui-bootstrap"
src="https://sdk.openui5.org/resources/sap-ui-core.js"
data-sap-ui-libs="sap.ui.core,sap.m,sap.ui.unified,sap.ui.layout"
data-sap-ui-theme="sap_horizon_dark"
data-sap-ui-async="true"
data-sap-ui-oninit="onUI5Init"
data-sap-ui-compatversion="edge"
data-sap-ui-excludejquerycompat="true"
data-sap-ui-xx-waitfortheme="init"
></script>
<body id="content" class="sapUiBody sapUiSizeCompact"></body>
API reference: sap/ui/model/type/DateTime
ODataModel
globalThis.onUI5Init = () => sap.ui.require([
"sap/ui/core/mvc/XMLView",
"sap/ui/model/odata/v4/ODataModel",
"sap/ui/core/mvc/Controller",
"sap/ui/core/Core",
], async (XMLView, ODataModel, Controller, core) => {
"use strict";
const control = await XMLView.create({
definition: `<mvc:View controllerName="demo.MyController"
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m"
xmlns:core="sap.ui.core"
core:require="{
TypeDateTimeOffset: 'sap/ui/model/odata/type/DateTimeOffset'
}"
displayBlock="true"
>
<App>
<Page
showHeader="false"
class="sapUiResponsiveContentPadding"
binding="{
path: '/People(userName=%27sandyosborn%27)/Trips(20)',
events: {
dataReceived: '.onDateTimeReceived'
}
}"
>
<ObjectAttribute
title="Model value"
text=""{ path: 'StartsAt', targetType: 'any' }""
/>
<ObjectAttribute title="Nullable" text="false" />
<DateTimePicker id="myDTP"
busy="true"
busyIndicatorDelay="1"
width="15rem"
value="{
path: 'StartsAt',
type: 'TypeDateTimeOffset',
formatOptions: {
style: 'medium/short'
},
constraints: {
nullable: false
}
}"
parseError="alert('Parse error')"
validationError="alert('Validation error')"
/>
</Page>
</App>
</mvc:View>`,
models: new ODataModel({
serviceUrl: "https://services.odata.org/TripPinRESTierService/(S(o1bizjomxywpc12mu2ad3fje))/",
autoExpandSelect: true,
operationMode: "Server",
}),
controller: new (Controller.extend("demo.MyController", {
onDateTimeReceived: function() {
this.byId("myDTP").setBusy(false);
},
}))(),
});
core.getMessageManager().registerObject(control, true);
control.placeAt("content");
});
<script id="sap-ui-bootstrap"
src="https://sdk.openui5.org/resources/sap-ui-core.js"
data-sap-ui-libs="sap.ui.core,sap.m,sap.ui.unified,sap.ui.layout"
data-sap-ui-theme="sap_horizon_dark"
data-sap-ui-async="true"
data-sap-ui-oninit="onUI5Init"
data-sap-ui-compatversion="edge"
data-sap-ui-excludejquerycompat="true"
data-sap-ui-resourceroots='{ "demo": "./" }'
data-sap-ui-xx-waitfortheme="init"
></script>
<body id="content" class="sapUiBody sapUiSizeCompact"></body>
API Reference: sap/ui/model/odata/type/DateTimeOffset
Documentation: "Dates, Times, Timestamps and Time Zones" (must-read)
Note
Unlike sap/ui/model/type/Date*, there is currently no support for minimum & maximum constraints in sap/ui/model/odata/type/* yet (Except for Decimal).
Until then, you could extend the DateTimeOffset type and implement the validateValue method accordingly. Sample: https://embed.plnkr.co/qatUyq
You have to use the fully qualified object name in your data type declaration as you're referring to a JavaScript object not to a build in HTML type. If you change the following part:
DateTime to sap.ui.model.type.DateTime
it will work. Please be aware that attributes like valueFormat or displayFormat as used in your example are ignored if a type is in use. In this case you have to provide these information in the binding. For further details please check the documentation of the type implementation.
An shortened example can be found here. More examples can be found in the UI5 Explored application which is in general a good starting point. An explanation of binding in general can be found here.
If you don't want to that much work in JS, I believe you can work with the validationError event. Simply set in in your XML, validationError="functionNameHere" and in your JS you can just set the ValueState to error. The validationError event is fired when the value can't be sent to the model, so you don't have to do any checks on the formatting, this event occurring means the formatting is indeed wrong. You can check the link below to read the documentation.
https://sapui5.hana.ondemand.com/#docs/api/symbols/sap.ui.base.ManagedObject.html#event:validationError

Display sum of bound numeric values in XML

I am using an OData model to bind UI controls with values. I need to sum two values from model values.
<Input id="__input8" class="rt1" value="{D1}" maxLength="1" type="Number" placeholder="" enabled="true" editable="true" />
<Input id="__input9" class="rt1" value="{D2}" maxLength="1" type="Number" placeholder="" enabled="true" editable="true" />
<Text id="__input15" class="rt1" text="{D1} + {D2}" />
I need to sum the D1 and D2 values in the Text control. I am using XML for view and JS for controller.
var oModel = new sap.ui.model.odata.ODataModel(sServiceUrl, true);
var oJsonModel = new sap.ui.model.json.JSONModel();
oModel.read("/xxxSet?", null, null, true, function (oData,repsonse) {
oJsonModel.setData(oData);
});
this.getView().setModel(oModel);
This is my OData connection.
You can use an Expression Binding:
<Text id="__input15" class="rt1" text="{= ${D1} + ${D2}}" />
Nice, finally a post where i can help.
First, i would set a formatter. Since my root usually is sap.ui.app, and my formatter is inside a model folder and called formatter, i can call it like "sap.ui.app.model.formatter"
You can check whats the name of your root inside your index.
data-sap-ui-resourceroots='{"sap.ui.app": "./"}'>
Thats your root. Create a folder inside sap.ui.app named model, and inside the model create a file called formatter.js and inside the file write this code.
jQuery.sap.declare("sap.ui.app.model.formatter");
sap.ui.app.model.formatter =
{
function1: (a, b)
{
return a+b;
}
};
Next, you should call the formatter from your view.
<Text id="__input15" class="rt1" text="{parts:[{path : 'D1'}, {path : 'D2'}], formatter:'sap.ui.app.model.formatter.function1'}" />
Thats it. It should work now.
EDIT: I'm glad my answer helped.

Passing parameter with React-Router in Meteor

I am learning MeteorJS, React and React-Router and I am having difficulty passing a parameter in the URL through the router. I have searched for the answer and I cannot find what I am doing wrong:
In my Routes.jsx file ('lists' is my MongoDB collection):
render: function() {
return (
<Router history={browserHistory}>
<Route path='/' component={Navbar}>
<Route path='/home' component={Home} />
<Route path='/register' component={Register} />
<Route path='/login' component={Login} />
<Route path='/listpages/:listId' component={ListPages} />
</Route>
</Router>
);
}
and in my MyLists.jsx file (inside the component):
renderLists() {
return this.data.lists.map((myList) => {
return
<li key={myList._id}>
<Link to='listpages' params={{ listId: myList._id}}>
{myList.name}
</Link>
</li>;
});
},
render() {
return (
<div>
<h2>Lists</h2>
<AddList />
<ul>
{this.renderLists()}
</ul>
</div>
);
}
When I click on one of the links for ListPages, I get the console error:
Warning: Location "listpages" did not match any routes
Also, the correct listId is embedded in the line item, but not the URL:
<li>
<Link to="listpages" params={listId: "qksabGvfeuf5PdaJv"} onlyActiveOnIndex=false...>
<a params={listId: "qksabGvfeuf5PdaJv" className="" style={}...>Inbox</a>
</Link>
</li>
But if I remove the parameter to this:
<Route path='/listpages' component={ListPages} />
then it works as expected and the contents of ListPages is displayed (right now it's only a heading to see if I get there). So ListPages does exists, but not when I pass the parameter. What am I doing wrong?
Thank you in advance for any help you can provide!
For anyone that may have stumbled upon this page doing a Google search:
This question may have been asked prior to the current version of React Router, but the correct way to do links with path='/route/:id' is to do <Link to={'/route/' + id} where the id is the thing you want to display. Since you're missing the key id part, you're getting an error.
For example, I want to show a table with a specific ID that I get as a prop.
Routes.jsx:
...
<Route path='/DisplayTable/:tableId' component={ Comp } />
...
Component I am going to display the table from (SelectTable.jsx):
...
<Link to={'/DisplayTable/' + this.props.tables[i]._id} />
...
You can pass your query parameter like this,
<Link to={{ pathname: 'listpages', query: { listId: myList._id } }}>
Thank you for the input. I made the change and the first time it loaded, I clicked the link and received the same error (Warning: Location "listpages" did not match any routes). When I refreshed to try it again, now the application crashes on startup with an unexpected token error on the line that you suggested.