how to pass along structure property via similar method to Bixby onclick - bixby

In a Bixby result-view on the Detail mode I want to provide the user with the option to select from one or more Actions and pass along a hidden parameter "identifier" that corresponds to a database field name to include in the http request made by the Action.
layout {
match: AltBrainsData (this)
mode (Details)
content{
section {
content {
image {
//aspect-ratio (16:9)
url {
template ("#{value(this.icon_image)}")
}
}
}
}
section {
content {
title-area {
slot1 {
text("[#{value(this.name)}]")
{style(Title_M)}
}
}
}
}
section {
content {
paragraph { value ("#{value(this.description)}") style (Detail_L) }
}
}
section {
content {
cell-card {
slot2 {
content {
order (PrimarySecondary)
primary ("Show me the latest news headlines")
}
}
on-click {
intent {
goal: altbrains.persistencetest.GetNews
value: altbrains.persistencetest.AltBrainsData("#{value(this.identifier)}")
}
}
}
}
}
...
I get an error saying that the value must be a primitive.
How can I accomplish this? Basically, I want the result "Detail" card to be populated with one or more possible Actions and each action should pass along this identifier to the corresponding function in code/.
A bit difficult to include all the necessary bits and pieces in Stack Overflow. The money part of the GetNews function is:
function getNews(AltBrainsData) {
const url = properties.get("config", "baseUrl") + "content"
console.log("i got this far and the url is ", url);
const query = {
apikey: properties.get("secret", "apiKey"),
q: "{\"" + "identifier" + "\":\"" + AltBrainsData.identifier + "\"}"
}

Change to the following:
on-click {
intent {
goal: altbrains.persistencetest.GetNews
value: $expr(this)
}
}
You can read more about $expr() syntax in expression language

Related

How to conditional statements in action output in Bixby

Hi I want to go to another action by putting a conditional statement in the action output.
What should I do?
For example
action (~~) {
description (Validate items passed from javascript)
collect {
input (~~) {
type (~~)
min (~~) max (~~)
}
}
type(~~~)
output (items){
on-empty(items.item1){ // if items.item1 is empty.
replan { // go to case1Action.
intent {
goal : case1Action
value : ~~~~~
}
}
}else{ // else
replan { // go to case2Action.
intent {
goal : case2Action
value : ~~~~~
}
}
}
}
or I want to select the view according to the output value.(Actually this is the purpose of the question)
output (items){
if(items.item1 == "goFirstCase"){
// First case view
}else{
// Second case view
}
}
I think by "select a different view according to the output value" I presume you mean you want to change what shows on the screen? because a "view" actually is comprised of the dialog, layout, and conversation-drivers.
https://bixbydevelopers.com/dev/docs/dev-guide/developers/building-views.views
For majority of use cases, there's really only one result-view that will be used, and any of the three contents of a view can be changed based on your preferred conditions as the above answer suggests.
within a view you can have the three different components defined with these three blocks: message for dialog, render for layout, and conversation-drivers
using your example,
//in a result-view
message {
if (items.item1 == "firstCase") {
template-macro (firstCase-result-dialog) {//enter params}
}
}
render {
if (size(items) > 1) {
list-of (items) {
where-each (item) {
if (item == "firstCase") {
layout-match (item) {
mode (Summary)
}
// OR use layout-macro
layout-macro (firstCase-result-summary-thumbnail-card) {//enter params}
}
}
}
}
}
similar conditional work can be done on conversation-drivers of course.
In your case, you would not need on-empty in action, but use template-macro-def as briefly explained in https://corp.bixbydevelopers.com/dev/docs/dev-guide/developers/refining-dialog.dialog-macros
// template file one
template-macro-def (id1) {
params {
param (x) {
Type (Items) ....
}
// template file two
template-macro-def (id2) {
// param x is type Items
}
//view file
result-view {
match: Items(this)
// after some checking make sure is single item
// it is possible to use other condition like if (this.sub1 == 2)
if (exists(this.sub1)) {
template-macro (id1) {
param (x) { expression (this) }
}
}
else {
template-macro (id2) {
param (x) { expression (this) }
}
}
The above would be the recommended way to handle different views for same concept in Bixby.
on-empty in action would be used for the purpose of either replan or relax some search condition in order to avoid 0 result. Bixby does not support on-empty(key) {} syntax according to https://corp.bixbydevelopers.com/dev/docs/reference/type/action.output.on-empty and on-empty would only apply in your case if output(items) itself is empty and would not check any sub-property of items.
Another option.
instead to use 'on-empty' block, you can use 'throws - error'
in action model,
output (items) {
throws {
error (case1ActionError) {
on-catch {
replan {
intent {
goal : case1Action
value : ~~~~~
}
}
}
}
error (case2ActionError) {
on-catch {
replan {
intent {
goal : case2Action
value : ~~~~~
}
}
}
}
}
}
And, in js code,,
if (error condition1) {
throw fail.checkedError('case 1 error', 'case1ActionError')
} else if (error condition2) {
throw fail.checkedError('case 2 error', 'case2ActionError')
}
For fail, refer to https://bixbydevelopers.com/dev/docs/reference/JavaScriptAPI/fail#failcheckederrormessage-errorid-errorobj

how to insert layout macro above thumbnail

I want to insert tiny type above the answer set providing a bit of metadata, but can't figure out how to do it. I just want the layout macro content-answer-set-info to say something like "results in reverse chronological order" in Legal or Detail_S. I want it to appear below altbrains workshop and above the first item in the list.
render {
if (size(this) > 1) {
list-of (this) {
has-details (true)
where-each (item) {
layout-macro (content-thumbnail-card) {
param (content) {
expression (item)
}
}
}
}
}
else-if (size(this) == 1) {
layout-match (this) {
mode (Details)
}
}
else {layout-macro (content-zero-results) {}
}
I would recommend wrapping this layout macro in a section and using the section-title (documentation) key to give it the text above the list.
There is an alternative solution that use section -> title but not with list-of
render {
layout {
section {
title {
template ("Voice command Add One")
}
content {
for-each (this) {
as (item) {
title-card {
title-area {
slot2 {
single-line {
text {
value {
template ("Integer: #{value(item.number)}")
}
style (Detail_L)
}
}
}
}
}
}
}
}
}
}

Bixby - getting user input for "yes/no" with navigation-mode in result-view

I have a result-view that reads and displays one item at a time:
if (size(this) > 1) {
list-of (this) {
has-details (false)
where-each (item) {
compound-card {
content {
image-card {
aspect-ratio (4:3)
title-area {
halign (Start)
slot1 {
text {
value ("#{value(item.title)}")
style (Title_M)
}
}
}
image-url ("#{value(item.thumbnail)}")
}
paragraph ("#{value(item.partialContent)}")
}
}
}
navigation-mode {
read-one-and-next {
page-content (item) {
underflow-statement ()
next-item-question ()
overflow-statement ()
overflow-question ()
page-marker {
if (isFirstNavPage(item)) {
choose (Random) {
template ("#{value(item.title)}. #{value(item.content)}. Do you want to hear more?")
}
}
else-if (isLastNavPage(item)) {
if (size(item) == 1) {
template ("#{value(item.title)}. You have reach the end of today's #{value(item.topic)}")
}
}
else {
choose (Random) {
template ("#{value(item.title)}. #{value(item.content)}. Do you want to hear more?")
}
}
}
}
}
}
}
}
The question I have is:
how do I get user voice input for "yes/no"?
the flow should be:
- if user said "yes" - reads the next item in the navigation-mode.
- if user said "no" - ends the navigation-mode.
I read something on using
followup
key for getting user yes/no input. But I struggle to find its use here. Should it be use alongside a converation-driver?
The next-page-question key serves as a the prompt for asking the user if they want the next item in the list. The user's "yes" or "no" response is handled by navigation mode without any additional coding from you.

Not sure how to update a struct with new information

A question concerning Bixby Studio.
I am trying to figure out how to accept text-input from the user.
I have a Filter struct with some fields such as SearchField, Genre, Platforms (Gaming consoles), and Themes (A few other entries)
By default, all of these are optional, especially with the search field. However, i would like for the user to be able to visibly see what filters are enabled, and be able to select and change their values (This values can be overwritten by NLP training, but I can't figure out how to disable the field.)
I created a result view for my filters and I've setup input-cells for selecting a specific field to modify. (In this case, SearchField.). I have been successful in redirecting to an input-view, but it seems that no matter what text I put in here, it does not save or apply to my filter.
Looking for some insight into the problem and willing to provide more information as needed.
Some of the things that I have tried in the past, seem to want take the existing context "SearchField" within the filters (which might not exist) and apply it to the new "search field". However, this doesn't work and seems to create a loop.
I've also tried to set the prompt-behavior (AlwaysSelection) in the action model for SetSearchField, but it appears to do nothing.
// Result View for Filters
result-view {
match {
Filter(this)
}
message {
template (Active Filters){
speech (Would you like to change any filters?)
}
}
render {
layout-macro (filter-details) {
param (filter) {
expression (this)
}
}
}
}
// Layout Macro
layout-macro-def(filter-details) {
params {
param (filter) {
type (Filter)
min (Required)
max (One)
}
}
content {
section {
title (Filters)
content {
input-cell {
label (Search Name)
value ("#{value(filter.name)}")
on-click {
intent {
goal: SetSearchField // <-------- Field in question
}
}
}
}
}
}
}
// Input-view for SearchField
input-view {
match {
SearchField(searchField)
}
render {
form {
elements {
text-input {
id (val)
type (SearchField)
required (true)
}
}
on-submit {
goal:SearchField
}
}
}
}
// SetSearchField action
action (SetSearchField) {
description (Sets the name in a search filter)
type (Fetch)
collect {
input (newSearchField) {
type (SearchField)
min (Required)
prompt-behavior (AlwaysSelection)
}
}
output (SearchField)
}
// SetSearchField endpoint
action-endpoint (SetSearchField) {
accepted-inputs (newSearchField)
local-endpoint ("filters/SetSearchField.js")
}
// .js file
module.exports.function = function setName (newSearchField) {
return newSearchField
}
I discovered there is a special way in accessing input form elements for input-views.
Collect input through the form -> elements, then reference them using the viv.core.FormElement(id)
input-view {
match {
SearchField(searchField)
}
render {
form {
on-submit {
goal: SearchField
value: viv.core.FormElement(text)
}
elements {
text-input {
id (text)
type (SearchField)
label (Search for: )
value("#{raw(searchField)}")
}
}
}
}
}

On click method on thumbnail-card in bixby

I am showing multiple choices on user's screen with thumbnail-card in bixby. Have added the slots for click as well. What I am trying to achieve is if user click on the thumbnail, i should get the id of the particular card and process it for further information.This is the layout
layout-macro-def (artist-thumbnail-card) {
params {
param (artistchoice) {
type (ArtistChoiceResult)
min (Required) max (One)
}
}
content {
thumbnail-card {
image-position (Start)
image-url ("#{value(artistchoice.multiple_image)}")
title-area {
halign (Start)
slot1 {
text {
value ("#{value(artistchoice.multiple_name)}")
style (Title_S)
}
}
slot2 {
single-line {
text {
value ("From #{value(artistchoice.multiple_cat)}")
style (Detail_L_Soft)
}
}
}
}
on-click {
intent {
goal: ArtistSearch
}
}
}
}
}
And this is the result view
result-view {
match: ArtistChoiceResult (artistchoice) {
from-output: ArtistChoice
}
message {
template ("Please select one of the following")
}
render {
if (size(artistchoice) > 1) {
list-of (artistchoice) {
has-details (true)
where-each (item) {
layout-macro (artist-thumbnail-card) {
param (artistchoice) {
expression (item)
}
}
}
}
} else-if (size(artistchoice) == 1) {
layout-match (artistchoice) {
mode (Details)
}
}
}
}
I am not able to send the ID information to the artistSearch Intent. How will I achieve that. And I have Id in other variable, so how do i pass that value?
Based on the code you have provided, we have to assume 2 things:
1) This is the result-view that is triggered for an artistchoice structure
2) The multiple_name is an array that holds all the options.
Given the above assumptions, you would need to build a layout where each of the elements of multiple_name (multiple_name[1], multiple_name[2], multiple_name[3], etc.).
Since one on-click event cannot be defined with variable click events, you would need to create a separate card for each multiple choice option so there is one on-click event per card. This would allow the on-click to look like the following:
on-click {
intent {
goal: ArtistSearch
value-set: [YOUR CONCEPT HERE]{$expr(artistchoice.multiple_name[1])}
}
}
If you need any further information, please reach out to the support team where we can discuss any particular issues you're facing that may be unique to your use case.

Resources