Appcelerator Titanium - Using Model as dynamic theme - titanium

Will this be a good idea:
I recently asked a question about themes (letting the user choose a theme and immediately applying it). To do this I had the thought of using Models and binding - which I used the opportunity to finally learn.
I got the desired result - creating a theme and applying it using a model with data binding, and in my test app I did the following:
app.tss
"Label": {
backgroundColor: "{theme.backgroundColor}"
}
(of course in a real app there will be much more definitions and much more bindings.
Doing this requires that I include my Model in every page like this (index.xml):
<Alloy>
<Model src="theme" />
<Window class="container" layout="vertical">
<View
id="test"
width="150"
height="150"
top="10">
</View>
<Label id="label" onClick="doClick" top="10">Hello, World</Label>
<Label onClick="doClick" top="10">Hello, World</Label>
<Label onClick="doClick" top="10">Hello, World</Label>
<Label onClick="doClick" top="10">Hello, World</Label>
<Label onClick="doClick" top="10">Hello, World</Label>
<Label onClick="doClick" top="10">Hello, World</Label>
<Label onClick="doClick" top="10">Hello, World</Label>
<Label onClick="doClick" top="10">Hello, World</Label>
<Label onClick="doClick" top="10">Hello, World</Label>
<Label onClick="doClick" top="10">Hello, World</Label>
<Label onClick="doClick" top="10">Hello, World</Label>
</Window>
</Alloy>
(In my real app I'm using an implementation of cross-platform navigation control so I will just pass this model when I open the window in a single place)
Obviously doing this kind of thing will create many binding for pretty much each element on the page. I don't exactly know what is going on behind the scenes, but I'm guessing that it creates a listener for each such binded value - which results in many listeners, a lot of overhead and generates more code for the page.
Guessing I'm pretty much answering my own question - is this path recommended to continue investigating? How bad is this?

It is possible using classes and re-applying them when it changes. You only have to monitor for an event at one place per controller
You can take a look at the example I wrote about dynamic styling based on orientation on GitHub
You can do that like this:
".DynamicLabel[if=Alloy.Globals.isPortrait]": {}
You should be using Backbone events, like also specified in the repository I linked above.
Alloy.js:
Alloy.Globals.events = _.clone(Backbone.Events);
Controller.js:
Alloy.Globals.events.on('orientationchange', () => {
But: This is very complicated and introduces complexity you don't need. The events part I wouldn't recommend for a complicated application. But.. it is possible!
What I would recommend for a complex application, is use the if filters in the tss and just close and re-open the controllers you want to have re-styled.

Related

Xamarin XAML Multi language in StringFormat

I have a simple (Android) application in Xamarin.
Until now, it uses a single language, now I add a translation for a second language. I use resource .resx files and I use it in XAML like this:
<Span Text="{x:Static resource:AppResources.Text1}" />
where Text1 is loaded from a resource file (depend on language).
I don't know how to do a similar thing in the next line, where I use Binding and StringFormat:
<Label Text="{Binding Datum, StringFormat='Some text: {0}'}" />
I tried with:
<Label Text="{Binding Datum, StringFormat='{x:Static resource:AppResources.Text2} {0}'}" />
but it didn't work.
Any idea?
use Spans to combine data and text
<Label>
<Label.FormattedText>
<FormattedString>
<Span Text="{x:Static resource:AppResources.Text1}" />
<Span Text="{Binding Datum}" />
</FormattedString>
</Label.FormattedText>
</Label>

Nativescript Vue: List data getting jumbled on top of each other

I have a list of data and when it renders, it's rendering on top of each other. The data is a fairly long list of objects and I am using multiple fields. I made a playground example by reducing the data list size and only using field (display_name) and it's still happening.
It seems to happen in random spots of the list but I am unsure as to how to resolve or more importantly, why it's happening. I thought it may have had to do with my key not being unique but I made sure it was and it's still happening. I included a playground and added screenshots. Any ideas?
Playground
Screenshots
EDIT: (Adding Template)
<RadListView
for="(movie,index) in this.movies"
ref="listView"
#loaded="onListLoaded($event)"
#itemTap="onItemTap($event)"
itemHeight="50"
:key="index"
gridSpanCount=1
>
<v-template>
<FlexboxLayout class="item-row" :key='`flex` + index' flexDirection="row" width="100%" height="100%" justifyContent="space-between">
<Stacklayout orientation="horizontal">
<Image :key='`img-flag` + index' marginTop="-22" class="flag-image" marginBottom="-22" :src="movie.image" height="100%" />
<Label :key='`display-name` + index' :text="movie.display_name" />
</Stacklayout>
<Image :key='`heart-1` + index' #tap="handleToggleFavorite(movie)" width="20" :src="movie.favorite ? heartFilled : heartUnfilled" />
</FlexboxLayout>
</v-template>
</RadListView>
Looking at your mockup, I think you can achieve it with a simple GridLayout.
<v-template>
<GridLayout columns="auto,*,auto" class="list-group-item">
<Image col="0" :src="movie.image"
class="m-5 thumb img-circle">
</Image>
<Label col="1" :text="movie.display_name"></Label>
<Image col="2" src="path_to_icon" class="thumb">
</Image>
</GridLayout>
</v-template>

Is it possible to render elements conditionally in NativeScript-Vue?

I hope you can help me to solve my problem.
I am working on a Nativescript-Vue Application and I want to render this conditionally:
<Label if="isRendering" text="This is a text"></Label>
But this does not work.
I already tried it with <v-template if="..."></v-template> but this also does not work.
If i am not mistaken, in Vue.js it is possible to render conditionally with v-if and i am searching for a possibility to make it in Nativescript-Vue.
Thank you
It's the same like in Vue.js.
Instead of using if you should be using v-if.
Playground example
Example:
<Label v-if="isRendering" text="This is a text"></Label>
But if you want to use an if in a ListView it's different.
Example:
<ListView for="item in listOfItems" #itemTap="onItemTap">
<v-template>
<Label :text="item.text" />
</v-template>
<v-template if="$odd">
<!-- For items with an odd index, shows the label in red. -->
<Label :text="item.text" color="red" />
</v-template>
</ListView>
But more info about that in the docs

Star rating control in Titanium Alloy?

I need to get the feedback star ratings for 5 questions, I'm using titanium alloy mobile development. For the same reason I have used the star rating widget from the below link,
https://github.com/AppceleratorSolutions/AlloyWidgets/tree/master/starrating
From the above link there is only one set of stars, But I need to use the star ratings for 5 times. How can I do that. I need the following format
1. Question?
*****
2. Question?
*****
3. Question?
*****
4. Question?
*****
5. Question?
*****
The widget is working fine but the stars are displaying only for one question, I need the stars for all the five questions, below is my current output,
questionnaire.xml:
<Alloy>
<Window id="questionnaireWin" title="Plan India" platform="android,ios">
<View id="header">
<Label id="title">Feedback</Label>
</View>
<Label id="question1" class="question">1. Question 1?</Label>
<Require type="widget" src="starrating" id="widget" name="widget" />
<Label id="question2" class="question">2. Question 2?</Label>
<Require type="widget" src="starrating" id="widget" name="widget" />
<Button class="button" onClick="submitRatings">Proceed</Button>
</Window>
</Alloy>
Though, I'm using widget twice it is showing only once. Please help how to do this?
Else any easy way to do this using any plugins or something esle?
You have required the same widget tow times using the same id. you should define different id.
<Alloy>
<Window id="questionnaireWin" title="Plan India" platform="android,ios">
<View id="header">
<Label id="title">Feedback</Label>
</View>
<Label id="question1" class="question">1. Question 1?</Label>
<Require type="widget" src="starrating" id="widget1" name="widget" />
<Label id="question2" class="question">2. Question 2?</Label>
<Require type="widget" src="starrating" id="widget2" name="widget" />
<Button class="button" onClick="submitRatings">Proceed</Button>
</Window>
and the in you js file initialize widget1 & widget2 ...
$.widget1.init();
$.widget2.init();
EDIT you can test this example that i have created ...

Titanium Alloy get all label text value from xml

I want to console log all label text value displayed from my xml, And this is how I was doing to log the label Ti.API.info($.label.getText()); , but this code doesn't seem to work since this only works for only a single value from a variable. How I'm going to do this? Sorry,Just so noob enough. Thanks!
<TableView id="table" dataCollection="person">
<TableViewRow id="row">
<Label id="label" text="{name}"></Label>
</TableViewRow>
</TableView>
from the Appcelerator documentation http://docs.appcelerator.com/titanium/latest/#!/guide/Alloy_Data_Binding
dataTransform: specifies an optional callback to use to format model attributes. The passed argument is a model and the return value is a modified model as a JSON object.
<TableView id="table" dataCollection="person" dataTransform="dumpText" >
<TableViewRow id="row">
<Label id="label" text="{name}"></Label>
</TableViewRow>
</TableView>
So we can use this method to dump whatever is being added to the list
function dumpText(model) {
// model to a JSON object
var o = model.toJSON();
Ti.API.info(o.name);
return o;
}