Titanium/ Alloy/ Appclerator: Remove event listener from a List Item - titanium

I have a ListView a bit like this:
<ListView>
<Templates>
<ItemTemplate name="example">
<View id="wrapper" onClick="onClickExampleButton">
<Label>Click Me</Label>
</View>
</ItemTemplate>
</Templates>
<ListSection id="ls">
<ListItem template="example"></ListItem>
<ListItem template="example"></ListItem>
<ListItem template="example"></ListItem>
</ListSection>
</ListView>
I want to prevent double click on the onClickExampleButton function.
So far in the controller I have code like this:
function onClickExampleButton(e) {
var item = $.ls.getItemAt(e.itemIndex);
// TODO: I want to disable the onClick eventListener here
someLongAsyncFuncToServer(function() {
// TODO: I want to re-enable the onClick eventListener here
})
}
Usually removing event listeners is as simple as
$.objId.removeEventListener(onClickExampleButton)
and re-adding it is as simple as:
$.objId.addEventListener(onClickExampleButton)
However, I am not sure how to achieve this on a ListItem

I believe you can achieve this by using source id of event fired by element. The only thing you need to take care of that since events are bubbled up to parent hierarchy, so any child-view can also invoke click event giving you unexpected source ids.
To resolve your query, you can safely use this code:
function onClickExampleButton(e) {
var item = $.ls.getItemAt(e.itemIndex);
// TODO: I want to disable the onClick eventListener here
e.source.touchEnabled = false;
someLongAsyncFuncToServer(function() {
// TODO: I want to re-enable the onClick eventListener here
e.source.touchEnabled = true;
})
}
And make a little change in your XML code like this:
<ListView>
<Templates>
<ItemTemplate name="example">
<View id="wrapper" onClick="onClickExampleButton">
<Label touchEnabled="false">Click Me</Label>
</View>
</ItemTemplate>
</Templates>
<ListSection id="ls">
<ListItem template="example"></ListItem>
<ListItem template="example"></ListItem>
<ListItem template="example"></ListItem>
</ListSection>
</ListView>
The catch here is that first of all you set touchEnabled = 'false' on Label inside View (with id = wrapper), it will make sure that click event won't be fired by Label, and will be bubbled up & fired by parent only.
Next thing is that, in click event method, you are using e.source which is now your wrapper View.
If you do not set touchEnabled=false on Label, then e.source can also contain Label reference. You can read more about events bubbling which will help you understand how you can work with event handling in Titanium efficiently.

I would put a property on the object and use it to determine status. For example,
set a variable when you click the button and then change it after the long running Async function... This way, if the status is running, then ignore the click. Once it is not running any longer, then accept the click.

Related

Calculating a popover position from a button click, instead of an SVG inside the button

I have been struggling for the past few hours to get a button click to work. The button contains text and an SVG, when clicking on it it opens a popover component.
The popover calculates its position on the element that was clicked upon. This works when clicking on the button itself, but when clicking on the SVG inside of the button, the dimensions/offsets from the SVG are used to calculate popover position instead.
What am I looking for: a way to bubble the click on the SVG to the button, then using the event object from the button click to calculate the popover position.
How my button with events looks like right now:
<button type="button"
#click="popButtonClicked">
Go do magical stuff
<svg path="" />
</button>
I have tried playing with #click.modifiers on both the button and SVG, but to no avail.. Hope someone has the answer for me! :)
You can get the button's reference by passing the $event as a parameter to your function, and then accessing the .currentTarget of that reference:
<button type="button"
#click="popButtonClicked($event)">
Go do magical stuff
<svg path="" />
</button>
And then in your function:
popButtonClicked (event) {
console.log(event.currentTarget)
}
Working codepen: https://codepen.io/anon/pen/gdBBdz

Titanium appcelerator how to update view inside listview?

I have an Appcelerator Titanium app to do, i have a Ti.UI.ListView with a view inside (view_one.xml):
...
<ListView onItemclick="getEvaluation" id="myLisview" defaultItemTemplate="templateLm" bottom="0" top="10" onItemclick="changePage" backgroundColor="white">
<Templates>
<Require id="lm_items" src="common/templateLm"/>
</Templates>
</ListView>
...
in common/templateLm :
<Alloy>
<ItemTemplate name="templatePageMission">
<View bindId="evaluate" height="10dp">
<Label text="evaluate"></Label>
</View>
<View bindId="stars" height="15dp"/>
</ItemTemplate>
</Alloy>
in view_one.js :
function getEvaluation(e){
switch(e.bindId){
case 'evaluate':
var item = e.section.getItemAt(e.itemIndex);
console.log(item) // <= this is empty ????
item.stars.backgroundColor = "red";
break;
}
}
and when click on the evaluate view I finally got:
undefined is not an object (evaluating item.stars.backgroundColor)
If anyone can help, this is great, anyway thanks for this great community.
You have assigned the itemclick event twice:
onItemclick="changePage"
and
onItemclick="getEvaluation"
So if you just use the latter one, it should catch the controller function correctly and the item should be updated correctly, since your controller code looks valid.

Xamarin Forms - Show Cancel button in toolbar items instead of Back (iOS)

I want to change the standard Back button in the NavigationBar on iOS to a Cancel button like the "New contact" screen in iOS.
I am using Xamarin Forms.
EDIT:
XAML of modal
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Xrm.Mca.Views.MyModalView">
<ContentPage.ToolbarItems>
<ToolbarItem x:Name="Cancel" Text="Cancel" ></ToolbarItem>
<ToolbarItem x:Name="Save" Text="Save" ></ToolbarItem>
</ContentPage.ToolbarItems>
<ContentPage.Content>
<TableView Intent="Form">
<TableRoot>
<TableSection Title="Details">
<EntryCell Label="Name" Placeholder="Entry your name" />
<EntryCell Label="Age" Placeholder="Entry your age" />
</TableSection>
</TableRoot>
</TableView>
</ContentPage.Content>
</ContentPage>
Code-behind in the prior screen to open modal
async Task OpenModal()
{
var page = new NavigationPage(new MyModalView ());
await App.Current.Navigation.PushModalAsync (page);
}
The standard convention of accomplishing your request is to push a Modal and use ToolBarItems. You can find an example of applying a ToolBarItem to your page on the Xamarin Forums.
Let me know if you need a more concrete example.
UPDATED WITH EXAMPLE
The two ToolbarItems would like like so:
var cancelItem = new ToolbarItem
{
Text = "Cancel"
};
var doneItem = new ToolbarItem
{
Text = "Done"
};
Now you can add these to your view:
this.ToolbarItems.Add(cancelItem);
this.ToolbarItems.Add(doneItem);
You can even bind the CommandProperty:
doneItem.SetBinding(MenuItem.CommandProperty, "DoneClicked");
Or simply handle the event when the user taps the item:
doneItem.Clicked += (object sender, System.EventArgs e) =>
{
// Perform action
};
Remember to wrap your Modal in a NavigationPage, as the ToolbarItems otherwise will not appear.
Hope this helps.
Do the following in the constructor of the page doing the navigation push. This will work for all pages pushed on to the stack.
NavigationPage.SetBackButtonTitle(this, "Cancel");
Where this is the ContentPage (or any type of page) of course

Titanium Alloy LeftNavButton not showing up in simulator

Not sure where I am doing wrong. I tried via code and by xml, but for some reason the left nav button does not show up. I am using the simulator since I don't have an actual device for ios.
The xml view
<!--filename: playType.xml->
<Alloy>
<Window class="container">
<LeftNavButton platform="ios">
<Button title="Back" onClick="closeWindow"/>
</LeftNavButton>
<View class="buttonContainer">
<Button class="menuButton" title="Single Player"/>
<Button class="menuButton" title ="Duel"/>
</View>
</Window>
</Alloy>
The Controller
//playType.js
var args = arguments[0] || {};
var closeWindow = function(){
$.playType.close();
};
The tss style
//playType.tss
".container" : {
backgroundColor:"white",
height:Ti.UI.FILL,
},
".buttonContainer":{
center:{x:"50%",y:"50%"},
height:Ti.UI.SIZE,
layout:"vertical"
}
I using this from the index.js
var playType = Alloy.createController('playType').getView();
playType.open();
The window shows up fine with the two buttons in the center but the back button doesn't appear.
What am I doing wrong. I went through the doc and also tried the code way too. Same result, no back button. :(
You have to create the window using navigation window otherwise navButton wont show up.here goes the code link for you
http://docs.appcelerator.com/titanium/3.0/#!/api/Titanium.UI.iOS.NavigationWindow
Thanks
Your window must be placed inside a TabGroup which handles all the capabilities of a navigation controller inside each tab.
<Alloy>
<TabGroup>
<Tab id="tab1" title="Tab 1">
<Window id="win1" title="Tab 1">
<LeftNavButton platform="ios">
<Button title="Back" onClick="closeWindow"/>
</LeftNavButton>
...
</Window>
</Tab>
</TabGroup>
</Alloy>
As for the back button, open a child window of the current tab using the tab as the reference to the open method.
tab.open(newWindow);

How to make a button event in pure xaml

I have this code
<Image Name="LightOn_BMP" Source="Res/LightOn.bmp" Canvas.Left="150" Canvas.Top="10" />
<Image Name="LightOff_BMP" Source="Res/LightOFF.bmp" Canvas.Left="150" Canvas.Top="10" />
<Button Canvas.Left="215" Canvas.Top="150" Click="PowerOn">
<Image Name="SwitchDown_BMP" Source="Res/SwitchDown.bmp" />
</Button>
<Button Canvas.Left="215" Canvas.Top="150" Click="PowerOff">
<Image Name="SwtichUp_BMP" Source="Res/SwitchUp.bmp" />
</Button>
And I want in pure XAML to make the PowerOn event to change so that LightOn.bmp is visible and LightOff.bmp is hidden and hide the Switchdown.bmp picture/button
Then I should be able to figure out how to make the event for the PowerOff
Simply put, you can't. The whole idea behind WPF is that you should separate behavior from display. So, at least without making some crazy black magic, you won't be able to change the state of the Image object (visible to false).