Formatter for metadata property binding in SAPUI5 - binding

I am using in my SAPUI5 application for metadata property binding a formatter.
It's returning a string, but the property needs a boolean, so I want to convert it. The problem is that the code of my formatter is not running. Did i forgot something?
var oInput = new sap.m.Input({
id: "oInput_" + column,
editable: {
path: "{inputModel>/#showcase/" + column + "/#sap:editable}",
formatter: function(v){
console.log(v);
if (v.includes("false")) {
return false;
} else {
return true;
}
}
}
});

Related

Vaadin: open calendar on field focus for datefield

Vaadin widgets are simple and awesome! But they are also poorly configurable.
I need my DateField widget to open calendar on focus event. I didn't find that functionality in official Vaadin documentation. I found some 3rd party widget here, but it's compiled for Vaadin 7.7 and I use latest Vaadin (8.0.6). Also it has Joda-time 2.1 dependency which is highly undesirable in my project. So, is there any simple way to tune stock vaadin DateField widget to open it's calendar on field focus, or do I need to write my own component for that? Any help is appreciated.
As I was saying in my comment, as far as I know, currently the framework does not offer an implicit way to programmatically open the calendar popup. The same thing goes for some other components such as the grid editor, or the combo item list.
One quick workaround I can think of, is to add a javascript extension that registers focus listeners for all date fields, and clicks the button when a date field is focused. Please find below a sample.
P.S. If you only need to apply this to only some date fields, you can add IDs and pass them to the JS, where you'll do something like document.getElementById('myDateFieldId') instead of document.getElementsByClassName("v-datefield").
1) Layout with components
public class MyDateFieldComponent extends HorizontalLayout {
public MyDateFieldComponent() {
// basic setup
DateField fromDateField = new DateField("From", LocalDate.of(2011, Month.FEBRUARY, 6));
DateField toDateField = new DateField("To", LocalDate.of(2018, Month.FEBRUARY, 6));
setSpacing(true);
addComponents(fromDateField, toDateField);
// add the extension
addExtension(new CalendarFocusPopupOpenerExtension());
}
}
2) Extension - java/server side
import com.vaadin.annotations.JavaScript;
import com.vaadin.server.AbstractJavaScriptExtension;
#JavaScript("calendar-focus-popup-opener-extension.js")
public class CalendarFocusPopupOpenerExtension extends AbstractJavaScriptExtension {
public CalendarFocusPopupOpenerExtension() {
// call the bind function defined in the associated JS
callFunction("bind");
}
}
3) Extension - js/client side
window.com_example_calendar_CalendarFocusPopupOpenerExtension = function () {
this.bind = function () {
if (document.readyState === "complete") {
// if executed when document already loaded, just bind
console.log("Doc already loaded, binding");
bindToAllDateFields();
} else {
// otherwise, bind when finished loading
console.log("Doc nod loaded, binding later");
window.onload = function () {
console.log("Doc finally loaded, binding");
bindToAllDateFields();
}
}
};
function bindToAllDateFields() {
// get all the date fields to assign focus handlers to
var dateFields = document.getElementsByClassName("v-datefield");
for (var i = 0; i < dateFields.length; i++) {
addFocusListeners(dateFields[i]);
}
}
function addFocusListeners(dateField) {
// when focusing the date field, click the button
dateField.onfocus = function () {
dateField.getElementsByTagName("button")[0].click();
};
// or when focusing the date field input, click the button
dateField.getElementsByTagName("input")[0].onfocus = function () {
dateField.getElementsByTagName("button")[0].click();
};
}
};
4) Result
LATER UPDATE
A second approach could be to assign some IDs to your fields, and then check periodically to see when all are visible, and as soon as they are, bind the focus listeners.
1) Layout with components
public class MyDateFieldComponent extends HorizontalLayout {
public MyDateFieldComponent() {
// basic setup
DateField fromDateField = new DateField("From", LocalDate.of(2011, Month.FEBRUARY, 6));
fromDateField.setId("fromDateField"); // use id to bind
fromDateField.setVisible(false); // initially hide it
DateField toDateField = new DateField("To", LocalDate.of(2018, Month.FEBRUARY, 6));
toDateField.setId("toDateField"); // use id to bind
toDateField.setVisible(false); // initially hide it
// simulate a delay until the fields are available
Button showFieldsButton = new Button("Show fields", e -> {
fromDateField.setVisible(true);
toDateField.setVisible(true);
});
setSpacing(true);
addComponents(showFieldsButton, fromDateField, toDateField);
// add the extension
addExtension(new CalendarFocusPopupOpenerExtension(fromDateField.getId(), toDateField.getId()));
}
}
2) Extension - java/server side
#JavaScript("calendar-focus-popup-opener-extension.js")
public class CalendarFocusPopupOpenerExtension extends AbstractJavaScriptExtension {
public CalendarFocusPopupOpenerExtension(String... idsToBindTo) {
// send the arguments as an array of strings
JsonArray arguments = Json.createArray();
for (int i = 0; i < idsToBindTo.length; i++) {
arguments.set(i, idsToBindTo[i]);
}
// call the bind defined in the associated JS
callFunction("bind", arguments);
}
}
3) Extension - js/client side
window.com_example_calendar_CalendarFocusPopupOpenerExtension = function () {
var timer;
this.bind = function (idsToBindTo) {
// check every second to see if the fields are available. interval can be tweaked as required
timer = setInterval(function () {
bindWhenFieldsAreAvailable(idsToBindTo);
}, 1000);
};
function bindWhenFieldsAreAvailable(idsToBindTo) {
console.log("Looking for the following date field ids: [" + idsToBindTo + "]");
var dateFields = [];
for (var i = 0; i < idsToBindTo.length; i++) {
var dateFieldId = idsToBindTo[i];
var dateField = document.getElementById(dateFieldId);
if (!dateField) {
// field not present, wait
console.log("Date field with id [" + dateFieldId + "] not found, sleeping");
return;
} else {
// field present, add it to the list
console.log("Date field with id [" + dateFieldId + "] found, adding to binding list");
dateFields.push(dateField);
}
}
// all fields present and accounted for, bind the listeners!
clearInterval(timer);
console.log("All fields available, binding focus listeners");
bindTo(dateFields);
}
function bindTo(dateFields) {
// assign focus handlers to all date fields
for (var i = 0; i < dateFields.length; i++) {
addFocusListeners(dateFields[i]);
}
}
function addFocusListeners(dateField) {
// when focusing the date field, click the button
dateField.onfocus = function () {
dateField.getElementsByTagName("button")[0].click();
};
// or when focusing the date field input, click the button
dateField.getElementsByTagName("input")[0].onfocus = function () {
dateField.getElementsByTagName("button")[0].click();
};
}
};
4) Result

BreezeSharp - Query with parameters against the local cache

I am trying to execute query with parameters against local cache or server (if nothing is found in cache).
public async Task<List<T>> Get(IDictionary<string, object> parameters, string resourceName = "", FetchSource fetchSource = FetchSource.None)
{
try
{
var query = resourceName == string.Empty ? EntityQuery.From<T>().WithParameters(parameters) : EntityQuery.From<T>(resourceName).WithParameters(parameters);
var queryResult = await this.ExecuteQuery(query, fetchSource);
var result = queryResult.ToList();
return result;
}
catch (Exception e)
{
return new List<T>(); // return empty result instead
}
}
FetchSource is our enum:
public enum FetchSource
{
None = 0,
FromServer = 1,
FromCache = 2,
FromCacheOrServer = 3
}
And here is ExecuteQuery method:
protected async Task<IEnumerable<T>> ExecuteQuery(EntityQuery<T> query, FetchSource fetchSource = FetchSource.None)
{
//...
if (fetchSource == FetchSource.FromCacheOrServer)
{
var result = query.ExecuteLocally(this.EntityManager); // Throws error
if (result != null && result.Any())
{
return result;
}
return await query.Execute(this.EntityManager);
}
//...
}
When I try to execute query locally this exception is thrown:
{"Unable to cast object of type
'WhereEnumerableIterator`1[StanleySteemer.Nimbus.Client.Common.Model.Proxy.RouteOrder]'
to type
'DataServiceOrderedQuery[StanleySteemer.Nimbus.Client.Common.Model.Proxy.RouteOrder]'."}
Although I couldn't find anything in docs specifically regarding to this subject, I have implemented similar functionality in BreezeJS which was working without issue(UPDATE: it doesn't work correctly):
findWithParametersInCacheOrServer = function (parameters, recordsLimit) {
var query = breeze.EntityQuery
.from(resourceName)
.withParameters(parameters);
var r = executeCacheQuery(query);
if (r) {
if (r.length > recordsLimit) {
return Q.resolve(r);
}
}
return executeQuery(query);
};
function executeCacheQuery(query) {
return entityManagerProvider.manager().executeQueryLocally(query);
}
Data architecture in JavaScript is similar to TempHire example.
Is this a known issue? Is there any workaround for it?
Not sure I understand, neither breeze.js nor breeze.sharp can automatically perform a 'local cache query' that involves parameters. This is because the interpretation of the parameters is only really defined on the server and not on the client.
It sounds as though what you have done is define a custom implementation of your specific 'with parameters' query in breeze.js that completely bypasses Breeze's internal implementation. Is this correct?

json TimeSpan return object

I work with Asp.net MVC4 (C#), I want to load data from controller to view.
from controller return an object in view, this object has an attribute of type TimeSpan (HH:DD:MM)
this is my function:
public JsonResult Buscar(string id){
string Mensaje = "";
Models.cSinDenuncias oDenuncia = new Models.cSinDenuncias();
oDenuncia.sd_iddenuncia = id;
var denuncia = Servicio.RecuperaDenuncia<Models.cSinDenuncias>(ref Mensaje, oDenuncia.getPk(), oDenuncia);
return Json(denuncia);
}
denuncia.sd_horadenuncia has for example this value 18:03:53 but I can't load this value when show in the view this is the value [OBJECT OBJECT]
In the view (Html.TextBoxFor):
$('#HoraDen').val(data.sd_horadenuncia);
How I can recover the correct value? (HH:MM:SS) and not [OBJECT OBJECT]
Regards
Ricardo
A TimeSpan is a complex type. This means that in your JSON it is serialized as such:
{
"sd_horadenuncia": {
"Ticks": 3000000000,
"Days": 0,
"Hours": 0,
"Milliseconds": 0,
"Minutes": 5,
"Seconds": 0,
"TotalDays": 0.003472222222222222,
"TotalHours": 0.08333333333333333,
"TotalMilliseconds": 300000,
"TotalMinutes": 5,
"TotalSeconds": 300
}
}
You are attempting to assign this complex object to a text field which obviously doesn't make sense.
You could use a view model on your controller action to preformat the value:
public ActionResult Buscar(string id)
{
string Mensaje = "";
Models.cSinDenuncias oDenuncia = new Models.cSinDenuncias();
oDenuncia.sd_iddenuncia = id;
var denuncia = Servicio.RecuperaDenuncia<Models.cSinDenuncias>(ref Mensaje, oDenuncia.getPk(), oDenuncia);
return Json(new
{
formattedHoradenuncia = denuncia.sd_horadenuncia.ToString()
});
}
and then inside your view you could use the new property:
$('#HoraDen').val(data.formattedHoradenuncia);
Another possibility is to access individual properties of this complex object and format the value yourself:
var hours = data.sd_horadenuncia.Hours;
var minutes = data.sd_horadenuncia.Minutes;
var seconds = data.sd_horadenuncia.Seconds;
$('#HoraDen').val(hours + ':' + minutes + ':' + seconds);

Knockout array filter and Computed observable not working

i am new to Knockout. I am trying out a scenario and i am not able to make it work. please help. I am using MVC4.
function ViewModel(data) {
var self = this;
this.Collection = ko.observable(data);
self.GetFilteredCollection = ko.computed(function () {
var filteredCollection = ko.utils.arrayFilter(self.Collection(), function (item) {
return item.IsSelected == true;
});
return filteredCollection;
});
self.FilteredCollectionCount = ko.computed(function () {
return self.GetFilteredCollection().length;
});
});
var collectionList = eval('<%= new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(Model.Collection) %>');
var VM = new ViewModel(collectionList);
ko.applyBindings(VM);
I have binded the IsSelected property to checkbox. Initially the IsSelected property will be set to false.
<span id="Span1" data-bind="text:$root.FilteredCollectionCount"></span>
I am always getting the Span value as 0 even if i select the checkbox. But i could see the Property IsSelected changed to true.
You need to make the IsSelected into a observable for the computed observable to be able to be notified when the value of IsSelected has changed
If it already is a observable then you need to change the code to
return item.IsSelected() == true;

Symfony - Propel - Value is not an integer

in my schema I set the size:
size: { type: bigint, required: true }
My generated 'base' model gives me:
public function setSize($v)
{
if ($v !== null) {
$v = (string) $v;
}
if ($this->size !== $v) {
$this->size = $v;
$this->modifiedColumns[] = TorrentPeer::SIZE;
}
return $this;
} // setSize()
Why does it case it to a string and not an integer?
I now receive the error:
"7818435653" is not an integer.
I tried changing the (string) to (int), but it did not work, I receive the same error. I'm confused why Propel made this value string when I specified bigint. Any help?
propel stores bigint as a string as PHP's integer type is too small: http://www.propelorm.org/wiki/Documentation/1.5/Schema#NumericTypes

Resources