How to pass/receive item detail from ListView tap event in Nativescript/JS? - nativescript

What I want to do (I think) is get the store.id from itemTap event and pass it along with the .navigate() so I can use it to fetch the correct data for the detail page, however I can't figure out how to get the tapped item.
I've got a list-page.xml:
<Page loaded="loaded" xmlns:lv="nativescript-ui-listview">
<ActionBar title="Bars"></ActionBar>
<GridLayout>
<ListView items="{{ storeList }}" row="1" itemTap="showDetail">
<ListView.itemTemplate >
<GridLayout class="grocery-list-item" >
<Label class="p-15" text="{{ name }}" />
</GridLayout>
</ListView.itemTemplate>
</ListView>
</GridLayout>
and list-page.js:
var dialogsModule = require("tns-core-modules/ui/dialogs");
var observableModule = require("tns-core-modules/data/observable");
var ObservableArray = require("tns-core-modules/data/observable-array").ObservableArray;
var page;
var StoreListViewModel = require("../shared/view-models/store-list-view-model");
var frameModule = require("tns-core-modules/ui/frame");
var storeList = new StoreListViewModel([]);
var pageData = new observableModule.fromObject({
storeList:storeList
});
exports.loaded = function (args) {
page = args.object;
page.bindingContext = pageData;
sindex = args.object.bindingContext;
storeList.empty();
storeList.load();
};
exports.showDetail = function() {
frameModule.topmost().navigate("views/detail/detail-page");
};
The storeList comes from my api and successfully sends back a list of stores which are rendered by the listview.
I've looked at a dozen other tutorials/questions, and several seem to mention getting it from either the args.index or args.object.bindingContext, but when I console.log(args.index) from the showDetail function, it's undefined. console.log(args.object.bindingContext) gives me a bunch of data, but it's identical regardless which row I click....
CONSOLE LOG file:///app/bundle.js:359:12: {
"_observers": {
"propertyChange": [
{}
]
},
"_map": {
"storeList": {
"_observers": {
"change": [
{}
]
},
"_array": [
{
"name": "Hipster's Coffee",
"address": "2200 Broadway, Oakland, CA 94612",
"id": 2
},
{
"name": "Suzy's Stationary",
"address": "630 Divisadero St., San Francisco, CA 94117",
"id": 3
}
],
"_addArgs": {
"eventName": "change",
"object": "[Circular]",
"action": "add",
"index": 1,
"removed": [],
"addedCount": 1
},
"_deleteArgs": {
"eventName": "change",
"object": "[Circular]",
"action": "delete",
"index": null,
"removed": null,
"addedCount": 0
}
}
},
"storeList": "[Circular]"
}
I'm very new to NativeScript, so obviously I'm missing something simple here.

<ListView items="{{ storeList }}" row="1" itemTap="{{showDetail}}">
Look at the sample playground here.

The function showDetail needs to access the received arguments. Just change the following in your code-behind file:
exports.showDetail = function(args) {
console.log(args); // Now there are arguments received from the itemTap event
frameModule.topmost().navigate("views/detail/detail-page");
};

Eventually figured out the proper way to extract the item details from the args:
var item = args.view.bindingContext;
and then I could access item.name, item.id, etc. and pass it through like so:
var navigationOptions={
moduleName:'views/detail/detail-page',
context:{
store_id: item.id
}
}
frameModule.topmost().navigate(navigationOptions);

Related

Vue3 apollo displaying query results using composition API

So I am using vue router and trying to display the graphql results on my page.
Here is the router link on index.js
{
path: '/clients/:id',
name: 'client_profile',
component: () => import('../views/client_profile.vue')
},
The link to the page is from a table with this code using the router-link, where an id is passed as a param:
<router-link :to="{ name:'client_profile', params: { id: data.id }}"> {{data.name}}
</router-link>
The dynamic link looks like this on the setup(), where the useQuery loads my query clientEntity:
setup(){
const route = useRoute(),
id = computed(() => route.params.id)
const { result } = useQuery(clientEntity,{
id: id.value,
})
const client = computed(() => result.value?.entities[0])
return{
client,
result
}
}
On the HTML if I put in {{client}} or {{result}} I get the following:
//results
{ "entities": [ { "address": "555 Fake Street", "name": "Test1", "notes": "", "phone": null } ] }
//client
{ "address": "555 Fake Street", "name": "Test1", "notes": "", "phone": null }
But if I try accessing some of the data like {{client.address}} or {{client.name}} the page turns blank and I get the following error:
[Vue warn]: Unhandled error during execution of render function
at <BaseTransition appear=false persisted=false mode=undefined ... >
at <Transition name="p-toggleable-content" >
at <Panel header="Description" toggleable=true style=
Object { "text-align": "left" }
>
at <ClientProfile onVnodeUnmounted=fn<onVnodeUnmounted> ref=Ref< undefined > >
at <RouterView>
at <App>
at <App>

SurveyJS Not Displaying

Trying to use surveyjs with laravel and vue, but when I try to get the survey from a api does not work.
I'm getting the data from a api in laravel controller.
surveyshow.vue
<template>
<div>
<survey :survey="survey"></survey>
</div>
</template>
created () {
...
let url = `/api/edit/i130`;
axios
.get(url)
.then(response => {
surveyJson = JSON.parse(response.data.data.json);
console.log(JSON.parse(response.data.data.json));
})
.catch(function (error) {
console.log(error);
});
this.survey = new SurveyVue.Model(surveyJson);
if I replace the variable using a constant works.
var surveyJson = {
pages: [
{
"name": "Address",
"title": "Address",
"questions": [
{
"type": "text",
"name": "address1",
"title": "Street Address",
"autocompleteAs": "placeautocomplete"
}, {
"type": "text",
"name": "address2",
"title": "Address Line 2"
}
]
}
]
};
You have a problem with the asynchronous aspect of your code. There is a callback function, which runs when the request to your api completes:
...
.then(response => {
surveyJson = JSON.parse(response.data.data.json);
console.log(JSON.parse(response.data.data.json));
})
...
but you are trying to load the survey json "outside" of it. In other words, this runs before the api request's callback has had a chance to load the survey's JSON:
...
this.survey = new SurveyVue.Model(surveyJson);
...
You should move the line that instantiates your survey inside the callback, like this:
...
.then(response => {
surveyJson = JSON.parse(response.data.data.json);
window.survey = new SurveyVue.Model(surveyJson);
})
...

Retrieving object from TreeMap

I've been working with few charts of amCharts 4, and everytime I struggled to subscribe to the event that returns the "selected/clicked" element. I don't know what I've been missing from the doc, but for example, I need to retrieve the selected item from "hit" event but i can't find anywhere (here is a simple i'd like to try this on https://codepen.io/team/amcharts/pen/erojQb)
var chart = am4core.create("chartdiv", am4charts.TreeMap);
chart.data = [{
"name": "First",
"value": 190
}, {
"name": "Second",
"value": 289
}, {
"name": "Third",
"value": 635
}, {
"name": "Fourth",
"value": 732
}, {
"name": "Fifth",
"value": 835
}];
/* Set color step */
chart.colors.step = 2;
/* Define data fields */
chart.dataFields.value = "value";
chart.dataFields.name = "name";
I tried this:
chart.seriesTemplates.template.columns.events.on('hit', function(ev) {
console.log('mlkmlz');
});
but not called, and this:
chart.seriesContainer.events.on('hit', function(ev) {
console.log(ev.target.dataItem)
});
but no dataItem attached
OK, so it's a bit more complicated than that. To attach events, you'll need to to actually create series for the specific level, then attach events on its column template:
var series = chart.seriesTemplates.create("0");
series.columns.template.events.on('hit', function(ev) {
console.log(ev.target.dataItem);
});

Adaptive Card rendered as image on FB shows "Title" text/element

I understand that adaptive cards are down-rendered as image on channels that does not support them. I just want to know how to either remove or set the "Title" element as shown on the fb channel:
The AdaptiveCard.Title element is deprecated and I did try setting that, it did not have any effect.
Here is my sample json:
{
"type": "AdaptiveCard",
"body": [
{
"type": "TextBlock",
"id": "Title",
"horizontalAlignment": "Center",
"size": "Large",
"weight": "Bolder",
"text": "See results on our website!"
},
{
"type": "Image",
"horizontalAlignment": "Center",
"url": "mylogo.png",
"size": "Stretch"
},
{
"type": "TextBlock",
"id": "Subtitle",
"horizontalAlignment": "Center",
"size": "ExtraLarge",
"text": "This channel does not allow us to display your results. Click the button to view it on our website.",
"wrap": true
}
],
"actions": [
{
"type": "Action.OpenUrl",
"id": "OpenUrl",
"title": "Take me there!"
}
],
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.0"
}
Unfortunately, when the BotFramewrok renders the card into an image for Facebook Messenger it adds the title above the actions which is strange. The only way to get rid of it is to remove the action from the card, which defeats its purpose in this case. An alternative is to send a Facebook Button Template in the activity's channel data instead of the adaptive card when the user is on Facebook Messenger. For more details checkout the Facebook Documentation on Button Templates and the code snippet below.
Screenshot
Bot Code - Node
async onTurn(turnContext) {
if (turnContext.activity.type === ActivityTypes.Message) {
if (turnContext.activity.channelId === 'facebook') {
await turnContext.sendActivity({
channelData: {
"attachment": {
"type": "template",
"payload": {
"template_type":"button",
"text":"This channel does not allow us to display your results. Click the button to view it on our website.",
"buttons":[{
"type":"web_url",
"url":"https://www.microsoft.com",
"title":"Take me there!"
}]
}
}
}
});
} else {
await turnContext.sendActivity({
attachments: [this.createAdaptiveCard()],
});
}
}
}
Hope this helps!
I had the same problem but I find an alternative using HeroCard.
If you are developing it with C# there it goes the code:
// first of all check if it is Facebook channel
// note that Channels is from Microsoft.Bot.Connector, the old one is deprecated.
if (turnContext.Activity.ChannelId == Channels.Facebook)
{
Activity replyToConversation = _flowService.ConvertMarkdownUrlToFacebookUrl(turnContext.Activity, response.Answer);
await turnContext.SendActivityAsync(replyToConversation, cancellationToken: cancellationToken);
}
public Activity ConvertMarkdownUrlToFacebookUrl(Activity message, string queryResponse)
{
var buttons = getButtons(queryResponse, out string result);
Activity replyToConversation = message.CreateReply();
replyToConversation.Attachments = new List<Attachment>();
List<CardAction> actions = new List<CardAction>();
foreach (var button in buttons)
{
actions.Add(new CardAction()
{
Title = button.Key, // text hyperlink
Type = ActionTypes.OpenUrl,
Value = button.Value // url
});
}
Attachment attachment = new HeroCard
{
Text = result, // your text
Buttons = actions
}.ToAttachment();
replyToConversation.Attachments.Add(attachment);
return replyToConversation;
}
You'll obtain something like this:
(sorry I had to delete the text)
Maybe it's not perfect (my first time with cards and attachments) but I hope that this will help someone 🙂

webix no scroll bar in treegrid

As title, no scroll bar even I did the setting below, I tried scroll:"y",scroll:"xy",scroll:true, scrollX:true, scrollY:true, etc. All failed.
I am thinking is it because the view is "treetable".
the code is as below:
let dataTree = function(){
const config={
// container:"testA", //the container is the div Id going to contain the grid, we will addd it # PlTreeGrid
view:"treetable",
//autowidth:true,
width:'100%',
//autoheight:true,
minHeight:530,
scroll:"xy",
scroll:"x",
scroll:"y",
scrollX:true,
scrollY:true,
columns:[
{ id:"id", header:"", css:{"text-align":"right"}, width:50, sort:"int"}, //,header:{ height:25 }
{ id:"value", header:"Film title", width:250,
template:"{common.treetable()} #value#", sort:"string" },
//{ id:"chapter", header:"Mode", sort:"string", template:"#value# <div class='edit'>Del</div>", width:300}//width:200, height:'auto'
{ id:"chapter", header:"Mode", sort:"string", width:'auto',fillspace:true}
],
onDblClick:{
"webix_remove_upload":function(ev, id){
console.log("ev,id");console.log(ev,id)
//this.remove(id);
}
},
data: [
{ "id":"1", "value":"The Shawshank Redemption", "open":true, "data":[
{ "id":"1.1", "value":"Part 1 l A", "chapter":"alpha"},
{ "id":"1.2", "value":"Part 2", "chapter":"beta", "open":true, "data":[
{ "id":"1.2.1", "value":"Part 1", "chapter":"beta-twin"}
]},
{ "id":"1.3", "value":"Part 3", "chapter":"gamma" }
]},
{ "id":"2", "value":"The Godfather", "data":[
{ "id":"2.1", "value":"Part 1", "chapter":"alpha" }
]}
]
}
let onItemDblClick = function(id, e, node){
alert("happy" + id, e, node);
}
return <TreeGrid config={config} onItemDblClick={onItemDblClick} />
No problems with the scroll bar.
Your code in snippet : http://webix.com/snippet/78021640
I've just removed any "scroll" attributes, to use the default one.
The scrollbar is only showed when needed. If you use the resizer to reduce the treetable size. The scrollbar will appear when part of content become hidden.

Resources