Alloy navigation between windows - view

I have 3 screen with alloy (appcelerator) :
index.xml
<Alloy>
<Window class="container">
<ImageView id = "actor" image="/images/f_logo.jpg"></ImageView>
<Label id = "bienvenue" onClick="doClick" > Bienvenue </Label>
<Label id = "apropos"> A propos </Label>
</Window>
</Alloy>
welcome.xml
<Alloy>
<Window class = "win2container">
<ImageView id = "bienvenue2" image="/images/f_logo.jpg"></ImageView>
<View id="texte" onClick="showTable">
<Label text="Afficher la liste" ></Label>
</View>
</Window>
</Alloy>
liste.xml
<Alloy>
<Tab title="Basic">
<Window title="Basic">
<ListView id = "liste" itemClick="onItemClick">
<ListSection>
<ListItem title="Row 1"></ListItem>
<ListItem title="Row 2"></ListItem>
<ListItem title="Row 3"></ListItem>
<ListItem title="Row 4"></ListItem>
<ListItem title="Row 5"></ListItem>
<ListItem title="Row 6"></ListItem>
<ListItem title="Row 7"></ListItem>
<ListItem title="Row 8"></ListItem>
<ListItem title="Row 9"></ListItem>
<ListItem title="Row 10"></ListItem>
<ListItem title="Row 11"></ListItem>
<ListItem title="Row 12"></ListItem>
</ListSection>
</ListView>
</Window>
</Tab>
</Alloy>
index.js (works)
function doClick(e) {
var win = Alloy.createController("welcome").getView();
win.open();
}
$.index.open();
welcome.js (I want to open liste windows)
function showTable(e){
var liste = Alloy.createController("liste");
liste.getView().open();
}
When i click on index label it open welcome window and when i click on welcome view it do nothing, my aim is to discover how to navigate between many windows (view files) with alloy.
Secondly i see on google, it is a good practice to close previous windows like this :
$.win.close();
$.win = null;
When i put this code inside index.js after $.win.open() it doesn't works (ie: i got error)
function doClick(e) {
var win = Alloy.createController("bienvenue").getView();
win.open();
$.win.close(); // or win.close() ?
$.win = null; // or win = null ?
}
Any suggestions? i tried many times without success.
Thanks all.

Regarding the close() being good practice, yes and no.
If you want the window to be there when the user navigates back with the back button, then no, because in essence, it will be closed.
function doClick(e) {
var win = Alloy.createController("bienvenue").getView();
win.open();
$.win.close(); // DEFINITELY $.win, as you created a var named win for your new window
$.win = null; // and $.win is the equivalent of findViewById("win")
}
By the way, the way you're opening windows, you won't be able to leverage the navigation (hadware back in Android, soft-back in iOS navigation)
With Android, I typically write my own manager to determine which window currently has the focus, and what happens when you go back.
With iOS, you should use something like this to add your window succession to the navigation section
var controllerWindow = Alloy.createController("bienvenue") // changed win to controllerWindow for clarity
var nav = Titanium.UI.iOS.createNavigationWindow({
window: controllerWindow
});
nav.open();

I believe the answer you are after is how to close the previous window, where the action is triggered from, while opening a new one.
Your example simply creates and opens a new window. Then closes it. What you need to do is to close the previous window. If you provided an id for the previous window, then you can close is with $.id.close().

Related

xamarin Syncfusion carousel with dots

I have a implement syncfusion Carousel and binding items using ItemTemplate.When i load the items to Carousel all item appears in Carousel view.But i need to add a doted indicator for it.
When user swipe though the Carousel by the dots should indicate current position.
When reading from documentation of syncfusion rotator have this functionality.
I need to add this to carousel view.
Here you can find all the SfCarousel Class Members.
And there's no property for the dots you refered in the SfCarousel print.
In fact, I think you are confusing it with another component called SfRotator. (that has an identical example like your print). and the property you are looking for is called: DotPlacement.
And can have the following states:
None //No Dots
Default //Dots Inside the Rotator View
OutSide //Dots Outside the Rotator View
We have analyzed your query and currently we don’t have dots view support in CarouselView. However, we can fulfill this requirement by using Border or Button control as like below code snippet.
Custom DotsView:
XAML:
<border:SfBorder BorderColor="{Binding ThumbBorder}" HorizontalOptions="Center" VerticalOptions="Center" BorderWidth="5" CornerRadius="50" />
Carousel View:
XAML:
<carousel:SfCarousel x:Name="carousel" Grid.Row="0" Offset="0" ItemsSource="{Binding ImageCollection}" ItemTemplate="{StaticResource itemTemplate}"
ItemHeight="200" SelectionChanged="Carousel_SelectionChanged"
ItemWidth="200" />
<StackLayout Grid.Row="1" HorizontalOptions="Center" x:Name="rotatorThumb" BackgroundColor="Transparent" Orientation="Horizontal"/>
C#:
public MainPage()
{
InitializeComponent();
Command command = new Command((object thumb) =>
{
var thumbView = thumb as DotsView;
if (thumbView != null)
{
((rotatorThumb.Children[carousel.SelectedIndex] as DotsView).BindingContext as CarouselModel).
ThumbBorder = Color.LightGray;
carousel.SelectedIndex = thumbView.Index;
(thumbView.BindingContext as CarouselModel).ThumbBorder = Color.Red;
}
});
for (var i = 0; i < ImageCollection.Count; i++)
{
var itemView = new DotsView() { BindingContext = ImageCollection[i], Index = i };
if (carousel.SelectedIndex == i)
(itemView.BindingContext as CarouselModel).ThumbBorder = Color.Red;
TapGestureRecognizer thumbTap = new TapGestureRecognizer();
thumbTap.Command = command;
itemView.GestureRecognizers.Add(thumbTap);
thumbTap.CommandParameter = itemView;
rotatorThumb.Children.Add(itemView);
}
}
Output:
Sample

Hide tab buttons on Nativescript-Angular TabView

I'm trying to find a way to remove the tab buttons on a element with an Angular 6 app but with no avail so far. Basically, I only want to keep the Tab contents and their swipe functionality.
Apparently there are specific android and iOS methods you can use but I'm unsure how to do that.
<TabView [(ngModel)]="tabSelectedIndex" (selectedIndexChanged)="onSelectedIndexChanged($event)" (loaded)="tabViewLoaded($event)">
<ng-container *ngFor="let article of articles" #tabView>
<StackLayout *tabItem="{title: article.id}">
<StackLayout>
<NewsDetails></NewsDetails>
</StackLayout>
</StackLayout>
</ng-container>
</TabView>
On my .ts file I can find a reference to the element like this:
#ViewChild("tabView") tabView: ElementRef;
ngAfterViewInit() {
console.dir(this.tabView.nativeElement);
}
But I have no idea what to do from now on. Any ideas? All previous questions regarding this have not worked.
Here is a sample playground link: https://play.nativescript.org/?template=play-ng&id=iK9ZTM
Use the code below with the loaded event of TabView.
onTabViewLoaded(event: EventData) {
const tabView = <TabView>event.object;
if (isIOS) {
tabView.viewController.tabBar.hidden = true;
}
if (isAndroid) {
const tabLayout = tabView.nativeViewProtected.tabLayout;
tabLayout.getLayoutParams().height = 0;
tabLayout.requestLayout();
}
}
I recently did that for a sample work I posted in Uplabs

Xamarin Forms Conditional statements

Hello guys: Am stuck with my code here. There is a point in my app where I need to notify users to register and sign in order to save their preferences. I have been trying to add a display alert inside a ViewModel but it's not working. Please help I am stuck.
ApproveViewModel
namespace MyApp.ViewModels
{
public class ApproveViewModel
{
private DataService dataService = new DataService();
public Oppotunity SelectedOppotunity { get; set; }
public ICommand SaveCommand => new Command(async () =>
{
await dataService.PostSaveOppotunity(SelectedOppotunity, Settings.AccessToken);
});
public ApproveViewModel()
{
SelectedOppotunity = new Oppotunity();
}
}
}
ApprovePage.xaml
<ScrollView>
<StackLayout Padding ="15">
<Label Text ="{Binding SelectedOppotunity.Title}"/>
<Label Text ="{Binding SelectedOppotunity.Description }"/>
<Label Text ="{Binding SelectedOppotunity.Organisation}"/>
<Label Text ="{Binding SelectedOppotunity.Venue }"/>
<Label Text ="{Binding SelectedOppotunity.Eligibility}"/>
<Label Text ="{Binding SelectedOppotunity.Benefits}"/>
<Label Text ="{Binding SelectedOppotunity.Province}"/>
<Label Text ="{Binding SelectedOppotunity.Country}"/>
<Label Text ="{Binding SelectedOppotunity.OppotunityLink}"/>
<Label Text ="{Binding SelectedOppotunity.Category}"/>
<Label Text ="{Binding SelectedOppotunity.Deadline}"/>
<!--
<Switch IsToggled ="{Binding SelectedOppotunity.IsApproved}"></Switch>
-->
<Button Text ="Apply" BackgroundColor ="#A91717" TextColor ="White"
Command ="{Binding SaveCommand }"/>
</StackLayout>
The code i wish to invoke on saving:
if (!string.IsNullOrEmpty(Settings.AccessToken))
{
// Implement the SaveCommand from the ViewModel;
}
// Go to Login form to get an access token
else if (!string.IsNullOrEmpty(Settings.Username) &&
!string.IsNullOrEmpty(Settings.Password))
{
MainPage = new NavigationPage(new Login());
}
else
{
//Register first
MainPage = new NavigationPage(new NewRegisterPage());
}
Solution:
You can use MessageCenter subscriptions to work through this problem.
Xamarin.Forms MessagingCenter enables view models and other components
to communicate with without having to know anything about each other
besides a simple Message contract.
Subscribe - Listen for messages with a certain signature and perform
some action when they are received. Multiple subscribers can be
listening for the same message.
Send - Publish a message for listeners to act upon. If no
listeners have subscribed then the message is ignored.
Code in the View Model:
if (!string.IsNullOrEmpty(Settings.AccessToken))
{
// Implement the SaveCommand from the ViewModel;
}
// Go to Login form to get an access token
else if (!string.IsNullOrEmpty(Settings.Username) &&
!string.IsNullOrEmpty(Settings.Password))
{
MainPage = new NavigationPage(new Login());
}
else
{
//Register first
//if you want to notify users to register here, use MessageCenter.Send
MessageCenter.Send(this, "displayAlert")
MainPage = new NavigationPage(new NewRegisterPage());
}
Code in the View:
MessagingCenter.Subscribe<ViewModelName>(this, "displayAlert", (sender) => {
// do something whenever the "displayAlert" message is sent
DisplayAlert("notification", "you should register first", "ok");
});
Send the message where you want to display an alert in the viewModel.
For more information about MessageCenter, you can refer to https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/messaging-center
If you wan't to display an alert from the ViewModel you can:
Application.Current.MainPage.DisplayAlert();

NativeScript Angular 2 Get more data when Scroll to Bottom (endless scrolling)

HI for example below is my view
<ScrollView>
<StackLayout>
<StackLayout *ngFor="let kid of kids" id="kidList">
<StackLayout orientation="horizontal" class="some-class">
<Lable text="{{ kid.fname }} {{ kid.lname }}"></Lable>
<Lable text="{{ kid.age }} years ago"></Lable>
</StackLayout>
</StackLayout>
</StackLayout>
</ScrollView>
I want to append the more data getting from server to 'kidList' when scroll reaches to bottom of screen in {N} aAngular2.
It's very hard to me build the layouts and adding childs in 'js' like below(KidInformation has more data).
let stackLayout = new StackLayout();
stackLayout.addChild('something newly constructed with JS')
Is there a way we can do in My Component just by adding child as view by passing local parameters to view , I mean like in below way
let kidListStacklayout = view.getViewById(this.page, 'kidList');
kidListStacklayout.addChild('views/kid/kid-item.html')
and kid-item.html will look like
<StackLayout orientation="horizontal" class="some-class">
<Lable text="{{ kid.fname }} {{ kid.lname }}"></Lable>
<Lable text="{{ kid.age }} years ago"></Lable>
</StackLayout>
The stock list view supports what you want. Don't use a scrollview and adding more layouts to the screen. This will cause lag and other issues. A listview recycles UI view components to reduce overhead of the layout growing in size. You want to use the loadMore event on the list view. https://docs.nativescript.org/cookbook/ui/list-view
Of course as the comment above ^^^ the free UI suite from telerik provides the RadListView which also supports infinite scrolling with a loadMore event.
Find out how to do it ( using Angular & TypeScript) :
import { ScrollView, ScrollEventData } from "ui/scroll-view";
#Component({...})
class ComponentClass implements OnInit, AfterViewInit {
#ViewChild("scrollid") scrollView: ElementRef;
ngOnInit(){
let scrollv : ScrollView = <ScrollView>this.scrollView.nativeElement;
scrollv.on(ScrollView.scrollEvent, function (args: ScrollEventData) {
if(scrollv.scrollableHeight === args.scrollY){
console.log("load more items here !!! ");
}
});
}
}
The scrollv.scrollableHeight gets updated by itself.
Tested on android emulator only. Must work on both Plateforms.

Nativescript - Lost databinding after app resume

I have a View which is binded to a ViewModel (that inherits from Observable) with a TextField and a Switch.
When i change the values, all is binded perfectly and I can see my new values.
But if I go to the home screen and then, go back to the app, the values are erased.
The view is a basic form like a customer CRUD.
Here is the XML :
<Page xmlns="http://schemas.nativescript.org/tns.xsd"
loaded="loaded">
<!-- ... -->
<TextView text="{{ valueA }}" />
<!-- ... -->
<Slider value="{{ valueB }}" minValue="1950" maxValue="2016" />
</Page
Here is the code-behind :
let viewModel: ViewModel;
let page: Page;
export function loaded(args: EventData) {
page = <Page>args.object;
setTimeout(function() {
viewModel = new ViewModel();
page.bindingContext = viewModel;
}, 0);
}
Do you have any idea why i loose my form data ?
Most likely, when you come back to the app, the loaded event is fired where you are constructing the view model. You should try constructing in a different page event (navigatedTo) or persist the data using the "application-settings" module. Then read the values from app-settings when you are constructing the observable view model. Hope this helps.
https://docs.nativescript.org/ApiReference/application-settings/HOW-TO.html

Resources