I have a class that when clicked is styled differently.
I tried to have the element as:
<GridLayout (tap)="onHeaderClicked()" cssClass="table-header" [class.open]="isOpen"> </GridLayout>
however when trying to apply styling to:
.table-header.open{
}
the css is not getting applied, I have now had to resort to the following syntax and have 2 methods:
<GridLayout (tap)="onHeaderClicked()" cssClass="{{isOpen ? 'table-header-open' : 'table-header-closed' }}">
and create styles for these individually
is this possible in nativescript?
In case you want to add specific style on runtime, you could use ViewChild decorator and with its help to create new property, which is pointing to the GridLayout. With this property you could change existing style properties to this element.
app.component.html
<GridLayout #container (tap)="onHeaderClicked()" rows="auto" columns="auto" width="200" height="300" cssClass="{{isOpen ? 'table-header-open' : 'table-header-closed'}}">
<Label row="0" col="0" text="sample text" textWrap="true"></Label>
</GridLayout>
app.component.ts
import {Component, ViewChild, ElementRef} from "#angular/core";
import {setTimeout} from "timer";
import {View} from "ui/core/view";
import {GridLayout} from "ui/layouts/grid-layout";
import {Color} from "color"
#Component({
selector: "my-app",
templateUrl: "app.component.html",
})
export class AppComponent {
public isOpen:boolean;
#ViewChild("container") container: ElementRef;
constructor(){
this.isOpen = true;
var that = this;
setTimeout(function() {
that.isOpen=false;
},3000);
}
public onHeaderClicked()
{
let container = <GridLayout>this.container.nativeElement;
container.color=new Color("blue");
}
}
app.css
.table-header-open{
background-color: red;
}
.table-header-closed{
background-color: green;
}
Related
How to implement RadioButtons in Nativescript + Angular?
I have tried the RadioButton plugin but it has error during compile time.
I have seen a post on stackoverflow stating to use font-awesome but it seems far more difficult to group the radio buttons.
Is it that I am ignoring any other simple method to create UI for something like this :
Label => Question: Select the fruit you like the most?
Radio 1 : Mango
Radio 2 : Apple
Radio 3 : Kiwi
Radio 4 : Banana
Any help in creating such interface?
Using Nativescript 5.0
Try nativescript-checkbox plugin, setting the boxType to circle will give you radio button style. For Grouped Radio Buttons, simply uncheck other radio buttons in group when one is selected.
I am able to achieve it using the Switch property isUserInteractionEnabled.
btw, I use Nativescript-angular.
This will enable interaction with a Switch only if the selected value is different:
<Switch [checked]="selectedValue === 'Mango'" isUserInteractionEnabled="{{ selectedValue !== 'Mango' }}"></Switch>
After looking around and observing several popular ecommerce apps, I found "Dialog box with List" method suitable as common user is comfortable with it.
I have decided to follow this : https://docs.nativescript.org/angular/ui/ng-ui-widgets/dialogs
Meantime, I will be still happy to see pure radio button kind of interface for Nativescript which is good for close group apps having user base with technical background as against retail users.
After trying multiple plugins (all outdated regarding todays angular and nativescript versions). I've decided to try my own solution, which is using the Button nativescript component to emulate the radiobutton behaviour.
The style needs improving, but the basic behaviour is there.
To achieve this, I've created a generic component which I can use anywhere I need it.
Here is its code:
import { Component, Input } from "#angular/core";
import { RadioBtnChoice } from "./radio-btn-form-input.model";
#Component({
selector: "radio-btn-form-input",
templateUrl: "./radio-btn-form-input.component.html",
styleUrls: ["./radio-btn-form-input.component.scss"]
})
export class RadioBtnFormInputComponent {
#Input() choicesRadioBtns: RadioBtnChoice[];
constructor() {}
ngOnInit(): void {}
toggleSelected(choice: RadioBtnChoice): void {
this.choicesRadioBtns.forEach(choice => {
choice.isSelected = !choice.isSelected;
});
console.log(`onTapChangeValue changed value to: ${choice.name}, ${choice.value}, ${choice.isSelected} `);
}
}
.radio-btn {
padding-top: 5px;
padding-right: 20px;
padding-bottom: 5px;
padding-left: 20px;
border-width: 2px;
background-color: #ddd;
margin: 0;
}
.radio-btn.selected {
border-top-color: #555;
border-left-color: #555;
border-right-color: #CCC;
border-bottom-color: #CCC;
background-color: #bbbbbb;
}
<StackLayout orientation="horizontal">
<template *ngFor="let choice of choicesRadioBtns">
<Button text="{{choice.name}}" (tap)="toggleSelected(choice)"
class="radio-btn {{choice.isSelected ? ' selected' : ''}}">
</Button>
</template>
</StackLayout>
This is the model for the radiobuttons inputs:
export interface RadioBtnChoice {
name: string;
value: any;
isSelected: boolean;
}
And this is the form using it:
export class FormUsingRadioButtonsComponent implements OnInit {
public individual: Individual;
public SexType = SexType;
public sexChoicesRadioBtns: RadioBtnChoice[];
constructor() {
this.sexChoicesRadioBtns = [
<RadioBtnChoice> {
name: "male",
value: SexType.M,
isSelected: true
},
<RadioBtnChoice> {
name: "female",
value: SexType.F,
isSelected: false
}
];
}
}
<Scrollview orientation="vertical">
<StackLayout orientation="vertical">
<StackLayout class="input-field">
<Label text="sex" class="input-label"></Label>
<radio-btn-form-input [choicesRadioBtns]="sexChoicesRadioBtns" class="input"></radio-btn-form-input> <------------- Here it is
</StackLayout>
<StackLayout class="input-field">
<TextField class="input" hint="name" keyboardType="" autocorrect="false" autocapitalizationType="none">
</TextField>
</StackLayout>
<StackLayout class="input-field">
<TextField class="input" hint="surname" keyboardType="" autocorrect="false" autocapitalizationType="none">
</TextField>
</StackLayout>
<Button text="Add individual" class="-primary input-field"></Button>
</StackLayout>
</Scrollview>
I've been searching for this all over during the last 2 days so I decided to ask for help.
Imagine we have a parent component called ParentComponent and we have also a child component called SomeComponent.
SomeComponent template would be:
import {Component} from "#angular/core";
#Component({
selector: "SomeComponent",
template: `
<ActionBar title="TestApp">
</ActionBar>
<StackLayout style="margin-top:20;">
<Label text="Somenthing on top"></Label>
#CONTAINER CONTENT HERE#
<Label text="Something in the bottom"></Label>
</StackLayout>
`,
})
export class SomeComponent {}
..and ParentComponent template would be:
import {Component} from "#angular/core";
import {SomeComponent} from "../some/where/...";
#Component({
selector: "parent",
template: `
<SomeComponent>
<Label text="Something here"></Label>
<Label text="Something else here"></Label>
</SomeComponent>
`,
})
export class ParentComponent {}
Considering the aforementioned example, how can I get the content inside "< SomeComponent >" defined in my ParentComponent, to be displayed properly in the SomeComponent in the reserved "#CONTAINER CONTENT HERE#" area?
In theory it is as if I would end up with something like this:
<ActionBar title="TestApp">
</ActionBar>
<StackLayout style="margin-top:20;">
<Label text="Somenthing on top"></Label>
<Label text="Something here"></Label>
<Label text="Something else here"></Label>
<Label text="Something in the bottom"></Label>
</StackLayout>
It looks like something pretty simple that I used to do in react native, that I can't get to work on NS.
Thanks in advance.
You can use a ng-content tag to transclude the content from the parent container to the child. I believe all you need to add ng-content to your SomeContent component, which will then look like:
import {Component} from "#angular/core";
#Component({
selector: "SomeComponent",
template: `
<ActionBar title="TestApp">
</ActionBar>
<StackLayout style="margin-top:20;">
<Label text="Somenthing on top"></Label>
<ng-content></ng-content>
<Label text="Something in the bottom"></Label>
</StackLayout>
`,
})
export class SomeComponent {}
You can read more about transclusion here https://toddmotto.com/transclusion-in-angular-2-with-ng-content
Also you can see a working example inside of the slides plugin I wrote https://github.com/TheOriginalJosh/nativescript-ngx-slides/blob/master/slides/app/slides/slides.component.ts#L40
I'm attempting to bind an Observable to a RadListView, without using any Page properties, but appear to be doing something completely wrong. The following is a minified version of the code.
The component:
export class WeatherComponent implements OnInit {
public weather : ObservableArray<StringWrapper>;
constructor(private _weatherService : WeatherService) {
this.weather = new ObservableArray<StringWrapper>([]);
this.weather.push(<StringWrapper>{value:'Sunny'});
}
ngOnInit(): void {
this._weatherService.getDummyWeather().subscribe(
item => {
this.weather.push(item);
}
);
}
}
The XML:
<RadListView [items]="weather">
<template tkListItemTemplate let-item="item">
<StackLayout orientation="vertical">
<Label [text]="item.value"></Label>
</StackLayout>
</template>
</RadListView>
The simple data model:
export interface StringWrapper {
value : string;
}
The service:
#Injectable()
export class WeatherService {
public getDummyWeather() : Observable<StringWrapper> {
return Observable.of(<StringWrapper>{value:'Rainy'});
}
}
The service is correctly updating the model but the view is not reflecting the changes, leading me to believe the problem is located in the observable binding.
Any help would be deeply appreciated!
N.B. Checked related questions and none of the solutions helped, i.e. Nativescript RadListView not binding to source property solution causes a build error.
Change the HTML to
<RadListView [items]="weather" >
<template tkListItemTemplate let-item="item">
<StackLayout class="itemStackLayout" >
<Label class="titleLabel" [text]="item.value" textWrap="true" width="100%"></Label>
</StackLayout>
</template>
</RadListView>
Hint: Seems like stringwrapper is not need. You can use below code if it just a string array
<Label class="titleLabel" [text]="item" textWrap="true" width="100%"></Label>
Is there a way to make a view 'transparent' to any user interactions? For example I have a view (with transparent background) and a button under that view. I want the user could tap the button under that view. If I have a scroller view under that view I want the user interacts with scroller when scroll over that view, so the view doesn't interfere or intercept user's gestures. But only this view should be transparent to user's interactions not its children. So, if I have a button inside that view it behaves normally.
Example XML:
<AbsoluteLayout width="100%" height="100%">
<Button text="Button1" tap="onTap1" />
<GridLayout width="100%" height="100%" backgroundColor="transparent">
<Button text="Button2" tap="onTap2" horizontalAlignment="center" verticalAlignment="center"/>
</GridLayout>
</AbsoluteLayout>
Thank you for your help.
You have multiple approaches to make a view change its color in NativeScript.
For example you can directly change its backgroundColor. Another oiption is to use animation and third option is to use CSS-animation.
Here is a basic example for the first two options.
page.xml
<Page xmlns="http://schemas.nativescript.org/tns.xsd" navigatingTo="navigatingTo">
<StackLayout>
<GridLayout width="300" height="300" id="myGrid" backgroundColor="transparent">
</GridLayout>
<Button text="Tap me" tap="onTap" />
<Button text="Or Tap me" tap="onAnotherTap" />
</StackLayout>
</Page>
page.js
import { EventData } from "data/observable";
import { Page } from "ui/page";
import { HelloWorldModel } from "./main-view-model";
import { GridLayout } from "ui/layouts/grid-layout";
import { Color } from "color";
var myGridView;
export function navigatingTo(args: EventData) {
var page = <Page>args.object;
page.bindingContext = new HelloWorldModel();
// get refference to the view using its id
myGridView = <GridLayout>page.getViewById("myGrid");
}
export function onTap(args:EventData) {
var color = new Color("#FF0000");
myGridView.backgroundColor = color;
}
export function onAnotherTap(args:EventData) {
myGridView.animate({
backgroundColor: new Color("#3D5AFE"),
duration: 3000
});
}
All of the options can be found described in NativeScript documenation
I'm having an issue with NativeScript 2.0 CSS and custom components. There seems to be a giant gap in my knowledge and I'm missing something vital that is non-obvious.
Take an empty NS 2.0 app created with
$ tns create test --ng
Delete the contents of app.css (to prevent side effects).
Change app.component.ts:
import {Component} from "#angular/core";
#Component({
selector: "my-app",
template: `
<StackLayout orientation="vertical">
<Label text="Label in first StackLayout"></Label>
<StackLayout orientation="vertical"
style="width: 80%;background-color: red;">
<Label text="Label in second StackLayout"></Label>
</StackLayout>
</StackLayout>
`,
})
export class AppComponent {}
Pretty basic stuff. Produces the following expected result:
Let's try to convert that inner StackLayout into a reusable component.
custom.component.ts
import {Component} from "#angular/core";
#Component({
selector: "Custom",
template: `
<StackLayout orientation="vertical"
style="width: 80%;background-color: red;">
<Label text="Label in second StackLayout"></Label>
</StackLayout>
`,
})
export class CustomComponent {}
Change the app.component.ts
import {Component} from "#angular/core";
import {CustomComponent} from "./custom.component"
#Component({
selector: "my-app",
directives: [CustomComponent],
template: `
<StackLayout orientation="vertical">
<Label text="Label in first StackLayout"></Label>
<Custom></Custom>
</StackLayout>
`,
})
export class AppComponent {}
Now the output looks like this:
The background color is applied but the width is not.
I even tried:
<Custom style="width: 80%;"></Custom> /* Does this even make sense? */
to no avail.
I realize percentages are experimental but suspect the error is in my code rather than NativeScript.
Where did I go wrong?
I reviewed your code in the given code snippet and found that it could be NativeScript issue. At the moment changing the width of the StackLayout in your CustomView using inline style will be working only on Android. To change the width of your CustomView using % for both platform at the moment you should setup this property in your css file and bind cssClass property.
custom.component.ts
import {Component} from "#angular/core";
#Component({
selector: "Custom",
template: `
<StackLayout orientation="vertical"
[cssClass]="styleView" style="background-color: red;">
<Label text="Label in second StackLayout"></Label>
</StackLayout>
`,
})
export class CustomComponent {
public styleView="customViewStyle";
}
app.css
.customViewStyle{
width:80%;
}