Google Apps Script CardService Switch value not in field inputs - google-apps-script

The documentation for the Switch class in Google Apps Script suggests that this is the right way to create a switch:
var switchDecoratedText = CardService.newDecoratedText()
.setTopLabel("Switch decorated text widget label")
.setText("This is a decorated text widget with a switch on the right")
.setWrapText(true)
.setSwitchControl(CardService.newSwitch()
.setFieldName("form_input_switch_key")
.setValue("form_input_switch_value")
.setOnChangeAction(CardService.newAction()
.setFunctionName("handleSwitchChange")));
But despite the call to setFieldName() here, when I try this I don't see the switch value in the formInputs object, despite it including everything else on the card.
Is there some way to retrieve the value of a switch here?

I wasn't quite following the documentation - I was calling setFieldName() but not setValue(). Once the switch has a value and is "on", you get a event.commonEventObject.formInputs.form_input_switch_key[""].stringInputs.value which is an array ["form_input_switch_value"]. If the switch is "off", the form_input_switch_key is missing from the formInputs object.

Related

Can I disable "Back" on a Google add-on card?

I'm building a Google add-on using Google Apps Script.
Is there any way to disable the Back button on a card (indicated below)?
Answer:
This is not possible.
More Information:
From the documentation on card navigation (emphasis my own):
...the 🡰 button is always available for the user to navigate from your contextual cards to your non-contextual cards.
It is actually possible with a get around (might be a bit messy). Here is the way I did it in case someone is looking for this :
I manage all navigations from a card to another so that it doesn't stack the cards, but instead pop the current card and add the new one, so I always only have one card in the stack, therefore having no "back" button in the header of the card.
So, appart from the homepage trigger from the manifest which return directly a card.build(), I navigate from card to card using a function such as :
function showMainCard(e) {
var card = buildMainCard();
var nav = CardService.newNavigation().popCard().pushCard(card);
var actionresponse = CardService.newActionResponseBuilder()
.setNavigation(nav);
return actionresponse.build();
}
And the build[something]Card() function returns the card.build()
The only drawback is that when the add-on is reloaded, it goes back to the first card you build in the homepage trigger. In order to get around this, you need to save page navigation in userProperties when building each card.
Then, the homepageTrigger can work this way to load the right card :
function onLoad(e) {
// Create the card
switch (userProperties.getProperty("pageNavigation")) {
case pages.MAIN:
return buildMainCard();
case pages.CREATE_NEW_FILE_REQUEST:
return buildNewFileRequestCard();
case pages.MANAGE_DEFAULT_OPTIONS:
return buildManageDefaultOptionsCard();
case pages.MANAGE_OPTIONS:
return buildManageOptionsCard();
case pages.CREATE_NEW_FILE_REQUEST_AFTER_AUTHORIZATION:
return buildNewFileRequestCard();
case pages.SHOW_FILE_REQUEST_DETAIL:
return buildFileRequestDetailCard();
case pages.EDIT_FILE_REQUEST:
return buildEditFileRequestCard();
default:
console.log("Problem with navigation, main card is loaded");
return buildMainCard();
}
}

How to fill Primefaces Autocomplete from Managed Bean

I have a primefaces autocomplete which is shown below:
<p:autoComplete value="#{consultaEventoCargoMBean.idUaSelecionada}" completeMethod="#{consultaEventoCargoMBean.completeUADestino}" var="ua" itemLabel="#{ua.name}" itemValue="#{ua.id}" forceSelection="false" appendTo="#this" />
Where idUaSelecionada and ua.id are Integer and ua.name is a String.
My issue is when I load my page to update the data. My idUaSelecionada is already filled and a object ready to be passed as suggestion (it would be a list of a only element). I was not able to find a way to fill this autocomplete - at least the text component.
Reading the Autocomplete souce code, I saw that there is a List called suggestions. Although there is not a setter for this list, it has a getter. But if I try something like autocomplete.getSuggestions().add(...) I get a NullPointerException. The only way I found to fill this list is through the method indicated by completeMethod tag attribute, who receives a String and returns a List.
I was not able to find in internet how to fill this List. That's why I am asking this to see if anyone has any answers.
Thanks,
Rafael Afonso
You can use JavaScript to trigger execution of method defined in completeMethod tag attribute and load suggestion(s).
Supposing that you want to do it when page loads, add this script to your page
<script>
function triggerSuggestionLoading() {
//finds autocomplete input text field
var autocomplete = document.getElementsByClassName('ui-autocomplete-input')[0];
//sets autocomplete query, for example
autocomplete.value="test";
//simulates key press triggering completeMethod to be executed
autocomplete.dispatchEvent(new Event('keydown'));
autocomplete.dispatchEvent(new Event('input'));
autocomplete.dispatchEvent(new Event('keyup'));
//sets focus on autocomplete
autocomplete.dispatchEvent(new Event('focus'));
//clears autocomplete text
autocomplete.value="";
}
window.onload = function() {
triggerSuggestionLoading();
};
</script>
Actually whenever you refresh your suggestion list and want to load suggestions into p:autocomplete just call triggerSuggestionLoading() method at the end (after all procedures are finished).
I've tested it in Chrome and Edge.

Using documentApp Text class methods in a google sheet

I have a range with rich text hyperlinks in it in a googlesheet, copied and pasted from elsewhere.
I want to create a function to extract the URLs - there's a method called .getLinkUrl in the text class that I think will do the trick.
However, SpreadsheetApp doesn't have a Text class, so I think I need the .getLinkUrl method from the Text class in DocumentApp.
I'd like to do something like this:
function getURL(range) {
var textElement = DocumentApp.create("temp").getBody().editAsText()
var url = textElement.setText(range.getValue()).getLinkUrl;
return url
}
But you can't do that because you can't create documents in custom functions.
I'd really like to avoid having to use a triggered script or something instead of a function but I can't work out how to do it without.
Any ideas?

How can I customize the filter function for SelectOneMenu

I tried to find on Primefaces Documentation but I have not found how can I customize the filter function for SelectOneMenu.
I add filterMatchMode="custom" filterFunction="#{mainRandevuBean.ilFilter()}"
But I don't know how can I write bean filterFunction.
The filter is a javascript (client-side) function. It all IS in the PrimeFaces documentation, which you should always look into first, carefully, thouroughly.
So use filterFunction="myFilter"
and create a javascript function like
function myFilter(itemLabel, filterValue) {
// return true if this label matches, false otherwise
}
Just as a sidenote: primefaces documentation doesn't say anything semantically about the parameters. It also does not mention where the label comes from (in fact, the docs mention "the item value" which is not very clear).
In fact I used the JavaScript function to debug this in order to figure out what was provided by default as a label.
function filterList(label, filter){
alert("label="+label+" and filter="+filter);
return false;
}
At first I thought it would be anything like the text inside the HTML generated for each list item. But when debugging it I saw the alert said that the label was something like my.package.SomeValueObject#123456 (which is obvously the Java object toString on each item in the list).
You need to define the itemLabel property on the selectItems which is inside the selectManyMenu to generate a proper text value used by the standard filtering mechanisme. As far as I could figure out that is the only reason why you have to put itemLabel there. In the documentation itemLabel is specified before explaining filtering which is confusing.
And as far as I know the itemValue defaults anyhow to just the object value, so I believe following from the documentation is redundant.
itemValue="#{player}"
Hope it helps anyone :.)
I resolve this problem with autocomplete component. Primefaces autocomplete component with dropdown="true" property works like one menu.

Filtering the iNotes Calendar in extlib

I need too filter the iNotes calendar control in extlib. When I look in the examples in the extlib application I can see that it is suppose to be connected to a xecalendarJsonLegacyService.
The problem I find with this service is that I can't filter the content based on category or search as with the other view services.
I need to create different calendars/json data based on a search or category in a view.
I have looked at some of the other services but not sure if it is possible to use them instead.
If you have any ideas for how I should create my filter, please respond.
I have attached pictures below showing both the jsonservice and the calendarcontrol.
This is what the json data look like in the xsCalendarJsonLegacyService
{
"#timestamp":"20120311T171603",
"#toplevelentries":"3",
"viewentry":
[
{
"#unid":"37F0330979C04AF2C12579BE004F5629",
"#noteid":"32E1A",
"#position":"1",
"#read":"true",
"#siblings":"3",
"entrydata":
[
{
"#columnnumber":"0",
"#name":"$134",
"datetime":
{
"0":"20120314T100000"
}
},
{
"#columnnumber":"1",
"#name":"$149",
"number":
{
"0":119
}
}, etc...
You could implement your own REST service (or extension to existing one) in an extension library, but I guess you are looking for something easier.
Sorry no code, but maybe (and hopefully) an answer.
Have you looked at the xc:CalendarStoreCustomRestService custom control inside the Xpages Extension Library demo? It looks like they connected the calendar control with a normal JSON view store and that supports search en keys.
I found code you could use but you will have to extend the custom control. I think it is a new component that is not yet included as a xe: component inside the Extension Library.
This is how you use the control:
<xc:CalendarStoreCustomRestService id="cc4ccCalendarStoreCustomRestService"
storeComponentId="notesCalendarStore1" databaseName="#{sessionScope.databaseName}"
viewName="($Calendar)">
</xc:CalendarStoreCustomRestService>
This is your calendar component, it uses the above storeComponentId.
<xe:calendarView id="calendarView1" jsId="cview1"
summarize="false"
type="#{javascript: null == viewScope.calendarType? 'M' : viewScope.calendarType }"
storeComponentId="notesCalendarStore1">
<xe:this.loaded><![CDATA[${javascript:if (sessionScope.databaseName == null) {
return false;
} else {
return true;
}}]]></xe:this.loaded>
</xe:calendarView>
If you need some more info, this example is included inside the DWA_iNotesRest.xsp.
I googled a long time and the only solution I`ve found is to build your own Rest service
have you managed to filter the Calendar without this?