Conditioan Appearance of Ionic Icons - ionic-view

can you please describe me how to change Ionic icon on conditioanal basis I want 'man' icon if gender is Male and 'woman' icon if gender is femal for example:

So ionic icons have icons like that:
<ion-icon name="man"></ion-icon>
<ion-icon name="woman"></ion-icon>
Source: https://ionicframework.com/docs/ionicons/
to make this conditional you need to create a binding from your template to a variable that defines if its "man" or "woman":
<ion-icon [name]="variableThatDefinesGender"></ion-icon>
Then in your ts file for the template you can assign relevant value (man or woman). Pseudo code below:
import { Component } from '#angular/core';
#Component({
selector: 'page-some',
templateUrl: 'some.html'
})
export class SomePage {
variableThatDefinesGender: string;
constructor(
) {
// initial value:
this.variableThatDefinesGender = "woman";
}
someMethod(condition) {
if (condition === "woman") {
this.variableThatDefinesGender = "woman"
} else {
this.variableThatDefinesGender = "man"
}
}
}

Related

VueJS cannot render a dynamically generated component

I'm struggling to make this work. I'm developing a VueJS small app, served using ParcelJS.
In a view called DisplayProgram, I'm trying to create multiple instances of a specific component ModuleListView, with network fetched data.
When I try to display the components, I get this error : [Vue warn]: Failed to mount component: template or render function not defined.
Here are the two views I'm using :
DisplayProgram.vue
<template lang="pug">
div.grix.xs4
div.col-xs4.row-xs5.row-md8.vself-stretch.vcenter
transition(:name="getSlideSide()" mode="out-in")
component(:is="getModuleListView()")
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
import ModuleListView from './ModuleListView.vue';
#Component({
components: {
'module-list': ModuleListView
}
})
export default class DisplayProgram extends Vue {
#Prop() program: any;
activeModuleList!: {name: string, number: number, modules: Array<any>};
activeModuleListNumber: number = 0;
previousModuleListNumber: number = 0;
moduleLists : Array<{name: string, number: number, modules: Array<any>}> = [];
listViews: Array<ModuleListView> = [];
async created() {
this.moduleLists = this.getModuleLists(this.program);
this.activeModuleList = this.moduleLists[0];
this.emitModuleListChanged(this.activeModuleList.number);
this.instanciateListViews();
}
instanciateListViews() {
this.moduleLists.forEach(moduleList => {
let moduleListView: ModuleListView = new ModuleListView(moduleList);
Vue.set(this.$options.components, moduleList.number, moduleListView);
this.listViews.push(moduleListView);
});
}
getModuleListView() {
return this.listViews[this.activeModuleListNumber];
}
getSlideSide() {
if (this.previousModuleListNumber > this.activeModuleListNumber) {
return "slide-right";
}
return "slide-left";
}
getProgramProgress() : {actualNumber: number, totalNumber: number} {
return {actualNumber: this.activeModuleListNumber + 1 , totalNumber: this.moduleLists.length};
}
getModuleLists(program: any) : Array<{name: string, number: number, modules: Array<any>}> {
// Getting data and generating the javascript objects
return moduleLists;
}
displayModuleList(index: number) {
this.emitModuleListChanged(index);
}
emitModuleListChanged(moduleListNumber: number) {
this.previousModuleListNumber = this.activeModuleList.number;
this.activeModuleList = this.moduleLists[moduleListNumber];
this.$emit("module-list-changed", {moduleList : this.activeModuleList, total : this.moduleLists.length});
this.activeModuleListNumber = moduleListNumber;
}
}
</script>
<style scoped>
</style>
ModuleListView.vue
<template lang="pug">
div
h2.txt-center.responsive {{moduleList.name}}
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
#Component({
components: {
}
})
export default class ModuleListView extends Vue {
#Prop() moduleList!: {name: string, number: number, modules: Array<any>};
constructor(moduleList: any) {
super();
this.moduleList = moduleList;
}
async created() {
console.log("modulelistview is created");
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.responsive {
font-size:3vw;
}
</style>
Do you have a solution for this, folks ? Thank you for your help !

How to change color of button text in popover in ionic 4

I am trying to change the text color on the button when the user has made the selection from a popover, so that when the user opens the popover again the previous selection is highlighted...It's for a filter list, user selects filter values desc or asc or by name, etc.
in my html file I have 3 buttons:
<ion-button class="btn1" (click)="sortList('Desc', 'secondary')" fill="clear" [color]="(colorSelect==='secondary')"? 'secondary':'tertiary'">Desc</ion-button>
<ion-button class="btn2" (click)="sortList('Desc', 'secondary')" fill="clear" [color]="(colorSelect==='secondary')"? 'secondary':'tertiary'">Desc</ion-button>
<ion-button class="btn3" (click)="sortList('Desc', 'secondary')" fill="clear" [color]="(colorSelect==='secondary')"? 'secondary':'tertiary'">Desc</ion-button>
in my Component file:
colorSelect: string = '';
public sortList(sortType, item: string){
this.popoverController.dismiss(sortType);
this.colorSelect = item;
}
How would you keep that item selected after the popover has closed so that when the popover is opened again, the item would be hightlighted?
Since popover uses a component that gets destroyed after popover is closed you need to leverage a service that popover component can import and use as source of truth for the button colors.
Very roughly:
https://stackblitz.com/edit/ionic-angular-v5-xfe357
At a high level:
service.ts:
import { Injectable } from '#angular/core';
#Injectable({
providedIn: 'root',
})
export class SharedService {
public filters;
constructor() {
this.filters = ["secondary","secondary","secondary"]
}
}
popover.ts:
import { Component } from '#angular/core';
import { PopoverController } from '#ionic/angular';
import { SharedService } from './shared.service';
#Component({
selector: 'hello',
template: `<h1>Hello!</h1>
<ion-list>
<ion-button class="btn1" (click)="sortList(0, 'Desc', 'secondary')" fill="clear" [color]="sharedService.filters[0]">Desc</ion-button>
<ion-button class="btn2" (click)="sortList(1, 'Desc', 'secondary')" fill="clear" [color]="sharedService.filters[1]">Desc</ion-button>
<ion-button class="btn3" (click)="sortList(2, 'Desc', 'secondary')" fill="clear" [color]="sharedService.filters[2]">Desc</ion-button>
</ion-list>
`
})
export class HelloComponent {
constructor(private sharedService: SharedService, private popoverController: PopoverController) {
}
sortList(buttonIndex, sortType, item: string){
if (this.sharedService.filters[buttonIndex]==="secondary") {
this.sharedService.filters[buttonIndex]="tertiary";
} else {
this.sharedService.filters[buttonIndex]="secondary";
}
this.popoverController.dismiss(sortType);
}
}
So your main component from which you call popover should also import such service (and inject it) and leverage data from it as single source of truth.

How to add Vuejs component dynamically to the DOM

I want to add a vue component to the DOM when an option is selected from the drop down list, so it's dynamically displayed
The code that I have tried is as follows
var html = "<component :is=\"dynamickeyvalue\"></component>";
$('#extraOptionsElements').html(html);
is there anyway to load the vue component when it's added as all I am getting now is blank.
I have used the component tag to load the component dynamically. The button click will simulate the component changing feature.
<template>
<button
#click="changeComponent()"
>Click me to change component</button>
<component
:is="theSelectedComponent"
></component>
</template>
<script>
import Component1 from '#/components/Component1'
import Component2 from '#/components/Component2'
import Component3 from '#/components/Component3'
export default {
components: {
Component1,
Component2,
Component3
},
data () {
return {
theSelectedComponent: 'Component1'
}
},
methods: {
changeComponent () {
if (this.theSelectedComponent === 'Component1') {
this.theSelectedComponent = 'Component2'
} else if (this.theSelectedComponent === 'Component2') {
this.theSelectedComponent = 'Component3'
} else {
this.theSelectedComponent = 'Component1'
}
}
}
}
</script>

Unable to dynamically reload component

I am trying to dynamically load a tab component based on screen resolution. I have a service with an observable with values: xl, md, sm, xs. The component initially loads on xs and then unloads on screen resizes. The problem is when you resize the screen back to under 768 (xs) the component is not fully materialized. I can see that the component is injected into the DOM on the second load, but it appears the directives are not rendered.
Plnkr - Try sizing the display full width, then resize back to smallest size to reload tab component
import {Component, bootstrap, DynamicComponentLoader, ElementRef, ComponentRef} from 'angular2/core'
import {UiTabs, UiPane} from './ui_tabs'
import {TabbedLayout} from './tabbed_layout'
import {ResizeSvc} from './resize_svc';
#Component({
selector: 'my-app',
template: `
<div>
<h2>Hello {{name}}</h2>
<div #location></div>
</div>
`,
providers: [ResizeSvc]
})
export class App implements OnInit{
private resizeSvc: ResizeSvc;
private _children:ComponentRef;
constructor(private _dcl: DynamicComponentLoader, private _e: ElementRef, pResizeSvc:ResizeSvc) {
this.name = 'Angular2'
this.resizeSvc = pResizeSvc;
}
ngOnInit() {
console.log('initialized app.ts');
this.resizeSvc.layout$.subscribe(
value => this.setLayout(value)
);
}
setLayout(pSize:string) {
this.removeAll();
if(pSize === 'xs') {
console.log('loading layout ' + pSize);
//this._dcl.loadIntoLocation(TabbedLayout, this._e, 'location').then((ref) => {
this._dcl.loadNextToLocation(TabbedLayout, this._e).then((ref) => {
ref.instance._ref = ref;
this._children = ref;
});
} else {
}
}
removeAll() {
if(this._children != null) {
console.log('Disposing layout...');
this._children.dispose();
this._children = null;
}
}
}
Here is a picture of the DOM when initially loaded
And here is a picture of the DOM on the second load with missing tabs
The order of <script> imports matters. angular2-polyfills.js has to be after system-polyfills.js. Here is your plunker working
I just moved the import below to the top of the list.
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.20/system-polyfills.js"></script>

Aurelia - Watch Dependency Value for Change

Suppose you have a class you are injecting into a another class or component. Is there a way to watch for changes on an attributed of the dependency you are injecting and act upon it?
For example, say you have the following app:
app.html
<template>
<input type="text" value.bind="item">
<button click.trigger="addToList()">Add</button>
<h3>Modded</h3>
<ul>
<li repeat.for="it of modded">${it}</li>
</ul>
<h3>Original</h3>
<ul>
<li repeat.for="it of dep.items">${it}</li>
</ul>
</template>
app.js
import {bindable, inject} from 'aurelia-framework';
import {Dep} from './dep';
#inject(Dep)
export class App {
constructor(dep) {
this.dep = dep;
}
attached() {
this.modifyItems();
}
addToList() {
this.dep.addItem(this.item);
}
modifyItems() {
this.modded = [];
for (let item of this.dep.items) {
this.modded.push(item.toUpperCase());
}
}
}
dep.js
export class Dep {
constructor() {
this.items = ['one', 'two', 'three'];
}
addItem(item) {
this.items.push(item);
}
}
Now, let's say that some other component modifies Dep.items. Is there a way to watch for changes in app.js on this.dep.items and then call modifyItems()?
Assume modifyItems() is more complex than this example so maybe a value converter is not the best option. (unless it is the only option I guess)
Here is working plunker with the above example: http://plnkr.co/edit/rEs9UM?p=preview
Someone pointed me to the BindingEngine.collectionObserver and it appears that is what I needed.
app.js:
import {inject} from 'aurelia-framework';
import {BindingEngine} from 'aurelia-binding';
import {Dep} from './dep';
#inject(Dep, BindingEngine)
export class App {
constructor(dep, bindingEngine) {
this.dep = dep;
let subscription = bindingEngine.collectionObserver(this.dep.items)
.subscribe((newVal, oldVal) => {
console.debug(newVal, oldVal);
this.modifyItems();
});
}
attached() {
this.modifyItems();
}
addToList() {
this.dep.addItem(this.item);
this.item = '';
}
modifyItems() {
this.modded = [];
for (let item of this.dep.items) {
this.modded.push(item.toUpperCase());
}
}
}
Here is the working pluker: http://plnkr.co/edit/Pcyxrh?p=preview