ion-picker outside the modal and inside the inline page - datetime

I would like a feature to enable the inclusion of the ion-picker component within the content of a page without the need to open it in a modal, I managed to implement this feature with ion-datetime but it only works with dates, years and months and I want to use ion-picker to create an ios-style select and only that with ion-picker I can create but it only opens in modal, is this feature currently possible or could it be developed?
I am currently using the following code in angular/ionic 6
home.page.html
<ion-content>
<ng-container >
<ion-button expand="block" (click)="showPickerController()">Show Picker Controller</ion-button>
<ion-list>
<ng-container *ngFor="let type of ['year']">
<ion-item slot="header">
<ion-label>ion-datetime</ion-label>
<ion-text slot="end"></ion-text>
</ion-item>
<ion-datetime
size="cover"
slot="content"
[presentation]="type"
>
</ion-datetime>
</ng-container>
</ion-list>
</ng-container>
</ion-content>
home.page.ts
import { Component } from '#angular/core';
import { PickerController, PickerOptions } from '#ionic/angular';
#Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage {
constructor(private pickerCtrl: PickerController) {}
async showPickerController() {
let opts: PickerOptions = {
buttons: [
{
text: 'Ok'
}
],
columns: [
{
name: 'category',
options: [
{ text: 'Dog', value: 'dog' },
{ text: 'Cat', value: 'cat' },
{ text: 'Fish', value: 'fish' },
{ text: 'Rabbit', value: 'rabbit' },
]
}
]
};
let picker = await this.pickerCtrl.create(opts);
picker.present();
picker.onDidDismiss().then(async data => {
console.log('dismiss');
});
}
}

Related

Passing information into sub component in storybook

Is there a way to pass information down though components in storybook that do not inheartly pass props though.
A proacticle example of this being that i have a language select button (usually pulls its information from a store so no information is passed to it), for storybook i have some props avaiable for this so i can run tests etc without having dirrect access to the store. this component on its own works fine.
On top of this i have a header nav bar that utlises this component, but does not pass informaton to it (as its self managed), however when trying to now set this component up in storybook the language select does not display as not having data.
I was reading though the multi-component documentation but struggling to get this to work for this use case and begining to wonder if this is going to be possiable and if so whats the best way to approach this.
in terms of code this is what i currently have
//header.vue
<template>
<div class="HeaderComponent">
//other component code here
<language-selector/>
</div>
</div>
</nav>
</div>
</template>
<script setup lang="ts">
import LanguageSelector from "#/components/HeaderAndFooter/LanguageSelector.vue";
import _ from "underscore";
import ImageModel from "#/helpers/classes/core/ImageModel";
import { defineProps } from "vue";
import HeaderNavigation from "#/helpers/classes/Navigation/HeaderNavigation";
// eslint-disable-next-line no-unused-vars
const props = defineProps({
menu: {
type: Object as () => {[key: string]: HeaderNavigation} | undefined,
default: undefined
},
icon: {
type: Object as () => ImageModel | undefined,
default: undefined
}
})
</script>
///languageSelector.vue
<template>
<div class="languageSelector" v-if="props.languages.length > 1">
<div class="dropdown">
<button class="btn btn-secondary dropdown-toggle" type="button" id="languageDropdownButton" data-bs-toggle="dropdown" aria-expanded="false">
{{currentLang.name}}
</button>
<ul class="dropdown-menu" aria-labelledby="languageDropdownButton">
<li v-for="language in props.languages" :key="language.i18n">
<a class="dropdown-item" href="#" #click="ChangeLanguage(language.i18n)">{{language.name}}</a>
</li>
</ul>
</div>
</div>
</template>
<script setup lang="ts">
import {useLanguageStore} from "#/store/languageStore";
import {computed, defineProps} from "vue";
import Language from "#/helpers/classes/Language";
const props = defineProps({
languages: {
languages: Object as () => Language[],
default: useLanguageStore().availableLanguages
},
})
const currentLang = computed(() => useLanguageStore().currentLanguage);
function ChangeLanguage(i18nCode : string)
{
useLanguageStore().updateCurrentLanguage(i18nCode);
}
</script>
///header.story.js
import LanguageSelector from "#/components/HeaderAndFooter/LanguageSelector.vue";
import { DefaultLangSelector } from './LanguageSelector.stories.js';
// More on default export: https://storybook.js.org/docs/vue/writing-stories/introduction#default-export
export default {
title: 'Framework/Header',
component: HeaderComponent,
// More on argTypes: https://storybook.js.org/docs/vue/api/argtypes
argTypes: {},
};
// More on component templates: https://storybook.js.org/docs/vue/writing-stories/introduction#using-args
const Template = (args) => ({
components: { HeaderComponent, LanguageSelector },
setup() {
return { args };
},
template: '<header-component v-bind="args" />',
});
export const Primary = Template.bind({});
Primary.args = {
menu: {
"Item 1": {
"children": {},
"id": "1",
"title": "Item 1"
},
"Item 2": {
"children": {},
"id": "2",
"title": "Item 2"
}
},
icon:
{
"url": "https://th.bing.com/th/id/R.25df89f6bbce9ce2324fb746d01940ea?rik=WpLZgCWrgPXbLA&pid=ImgRaw&r=0"
},
...DefaultLangSelector.args = {
languages: [
{"name" : "English", "i18n" : "en"},
{"name" : "Spanish", "i18n" : "es"},
],
}
};

React align right/hide items on ANTD 4.21 Menu

Is there a way I can add different classes or an attribute to align right 2 items of this ant design top navigation menu? Also how can I hide an item conditionally? IE if there's an user logged in, I want to hide an item.
import { HomeOutlined, SettingOutlined, LoginOutlined, UserAddOutlined} from '#ant-design/icons';
import { Menu } from 'antd';
import { useState } from 'react';
const items = [
{
label: 'Home',
key: 'home',
icon: <HomeOutlined />,
},
{
label: 'Username',
key: 'SubMenu',
icon: <SettingOutlined />,
children: [
{
type: 'group',
children: [
{
label: 'Option 1',
key: 'setting:1',
},
{
label: 'Option 2',
key: 'setting:2',
},
],
},
],
},
{
label: 'Login',
key: 'login',
icon: <LoginOutlined />
},
{
label: 'Register',
key: 'register',
icon: <UserAddOutlined />,
},
];
const Header = () => {
const [current, setCurrent] = useState('home');
const onClick = (e) => {
setCurrent(e.key);
};
return (
<Menu onClick={onClick} selectedKeys={[current]} mode="horizontal" items={items} />
);
};
export default Header;
I'm using ant design's top navigation menu: https://ant.design/components/menu/#API
I checked their documentation and other places but I can't seem to figure it out. I would appreciate any help.
Thanks
I don't know if it is too late to respond :)
As far as I know, there is no "one-line" solution for this. You should make the conditions with JS using conditional JSX.
For example (in JSX, in the return expression in your React Component):
{checkedCondition &&
<Menu type one .../>
}
{uncheckedCondition &&
<Menu type two .../>
}

Storybook Navbar component breaks through useRouter()

I have a Navbar with a Navigation Links, which are highlighted as active, depending on the page a user is on.
import { useRouter } from 'next/dist/client/router'
const navigation = [
{ name: 'Home', url: '/', active: true},
{ name: 'Quiz', url:'/quiz', active: false}
]
function classNames(...classes) {
return classes.filter(Boolean).join(' ')
}
export const Navigation = () => {
const router = useRouter();
return (
<div className="flex space-x-4 justify-self-center">
{navigation.map((item) => (
<a
key={item.name}
href={item.url}
className={`px-3 py-2 rounded-md text-sm font-medium ${
router.asPath === item.url ? "bg-gray-900 text-white" : 'text-gray-300 hover:text-gray-700'
}`}
aria-current={item.active? 'page' : undefined}
>
{item.name}
</a>
))}
</div>
)
}
It works as is should, but I can't create a story for it, because of the Next Router. I get the following error: Cannot read property 'asPath' of null.
I tried to follow the instructions in the answer I found here: How to use NextJS's 'useRouter()' hook inside Storybook , but unfortunately it didn't give me the result I am striving for. So basically my "Story-Navbar" shouldn't redirect, but just highlight the Navigation Link, while I click on it. Is that possible? Here is the story for Navigation:
import { Navigation } from './Navigation';
export default {
title: 'Example/Navigation',
component: Navigation,
};
export const DefautlNavigation = () => {
return (
<Navigation />
)
}
The storybook Next.js router add-on works for useRouter() hook. Here is the example in their docs:
import { withNextRouter } from 'storybook-addon-next-router';
import MyComponentThatHasANextLink from '../component-that-has-a-next-link';
export default {
title: 'My Story',
decorators: [withNextRouter], // not necessary if defined in preview.js
};
// if you have the actions addon
// you can click the links and see the route change events there
export const Example = () => <MyComponentThatHasANextLink />;
Example.story = {
parameters: {
nextRouter: {
path: '/profile/[id]',
asPath: '/profile/lifeiscontent',
query: {
id: 'lifeiscontent',
},
},
},
};

How do I display a route parameter (Vue / Firebase)

I'm creating a blog with free sewing patterns as content. I'm using route parameters to receive each blog individually. However, I'm getting a blank page when trying to retrieve its data from firebase firestore. Please help.
The blog's id appears on my address bar:
http://localhost:8080/#/admin/single-pattern/4LIS362IEWa7RKEv79g8
But it renders a blank page. I cant see my blog content.
This is my route path code. I've added a parameter of :id in my singlepattern. The SinglePattern component is where I will get the individual blog's data:
{
path: "/admin",
name: "admin",
component: Admin,
meta: {
auth: true,
},
children: [
{
path: "dashboard",
name: "dashboard",
component: Dashboard,
},
{
path: "manage-patterns",
name: "manage-patterns",
component: ManagePatterns,
},
{
path: "single-pattern/:id",
name: "single-pattern",
component: SinglePattern,
},
],
},
Here is my "ListPattern" component's code. ListPattern is where all my sewing blogs are displayed.
<template>
<div class="list-blogs">
<h1>LIST BLOG TITLES</h1>
<br />
<input type="text" v-model="search" placeholder="search blogs" />
<div
class="blog-cover"
v-for="pattern in filteredPatterns"
:key="pattern.id"
>
<div>
<router-link v-bind:to="'/admin/single-pattern/' + pattern.id">
<h3 style="cursor: pointer" v-rainbow>
{{ pattern.title | uppercase }}
</h3></router-link
>
</div>
<p
:style="'background-color: var(--lightgrey)'"
:inner-html.prop="pattern.description | snippet"
></p>
</div>
</div>
</template>
<script>
import firebase from "firebase";
import searchMixin from "../mixins/searchMixin";
// Basic Use - Covers most scenarios
import { VueEditor } from "vue2-editor";
import Quill from "quill";
const AlignStyle = Quill.import("attributors/style/align");
Quill.register(AlignStyle, true);
// import $ from "jquery";
import Swal from "sweetalert2";
window.Swal = Swal;
const Toast = Swal.mixin({
toast: true,
position: "top-end",
showConfirmButton: false,
timer: 3000,
});
window.Toast = Toast;
export default {
name: "ManagePatterns",
components: { VueEditor },
data() {
return {
patterns: [],
pattern: {
title: null,
description: null,
image: null,
},
search: "",
};
},
firestore() {
return {
patterns: firebase.firestore().collection("free-patterns"),
};
},
computed: {},
},
};
</script>
And this is my 'SinglePattern' component where the clicked blog/pattern is displayed.
<template>
<div class="single-pattern">
<div class="blog-cover">
<div>
</div>
<div v-if="pattern">
<h3 style="cursor: pointer">
{{ pattern.title }}
</h3>
<div v-if="pattern.description">
<p
:style="'background-color: var(--lightgrey)'"
:inner-html.prop="pattern.description"
></p>
</div>
</div>
</div>
</div>
</template>
<script>
import firebase from "firebase";
import searchMixin from "../../mixins/searchMixin";
export default {
data() {
return {
id: this.$route.params.id,
patterns: [],
pattern: {
title: null,
description: null,
image: null,
},
};
},
firestore() {
return {
patterns: firebase.firestore().collection("free-patterns"),
};
},
mixins: [searchMixin],
created() {
console.log(this.$route.params.id);
var pat = this;
firebase
.firestore()
.collection("free-patterns")
.doc(this.$route.params.id)
.get()
.then(function(doc) {
if (doc.exists) {
pat.pattern = doc.data().pattern;
} else {
console.log("no such doc");
}
});
},
methods: {},
};
</script>
It works. I just had to change the code in my created() hook in 'SingePattern' component.
created() {
console.log(this.$route.params.id);
var docRef = firebase
.firestore()
.collection("free-patterns")
.doc(this.$route.params.id);
docRef
.get()
.then((doc) => {
if (doc.exists) {
this.pattern = doc.data();
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
}
})
.catch((error) => {
console.log("Error getting document:", error);
});

How to modify the css for reactjs-dropdown-component?

Goal
I need to modify the CSS for the reactjs-dropdown-component.
Background/Overview
I've downloaded the dropdown, imported it, and have it fully operational in react. However, I'm fairly new to coding and haven't yet been in a situation where I need to do significant styling to a downloaded component. Do I just recreate the stylesheet for it and import it?
The css for this component is in this Github repo: https://github.com/dbilgili/Custom-ReactJS-Dropdown-Components/blob/master/src/styles/stylus/dropdown.styl
The instructions I followed for downloading/using this dropdown are here: https://github.com/dbilgili/Custom-ReactJS-Dropdown-Components
I'm not sure that it's necessary but here is code where I'm using the dropdown
import React from 'react';
import './EventContainer.css';
import { Dropdown } from 'reactjs-dropdown-component';
import { dining } from './EventContainerIcons.js';
class EventContainer extends React.Component {
constructor(props){
super(props);
this.state = {
...props.event,
activityIcon: [
{
id: 0,
title: <img src={dining} width="64" height="64" alt="dining icon" />,
selected: false,
key: 'activityIcon'
},
{
id: 1,
title: 'Orange',
selected: false,
key: 'activityIcon'
},
{
id: 2,
title: 'Strawberry',
selected: false,
key: 'activityIcon'
}
],
};
}
handleTypeChange = (e) => {
this.setState({
type: e.target.value
})
}
handleTimeChange = (e) => {
this.setState({
time: e.target.value
})
}
handleSummaryChange = (e) => {
this.setState({
summary: e.target.value
})
}
handleNotesChange = (e) => {
this.setState({
notes: e.target.value
})
}
resetThenSet = (id, key) => {
let temp = this.state[key];
temp.forEach(item => (item.selected = false));
temp[id].selected = true;
this.setState({
[key]: temp
});
};
render(){
return (
<div className="eventContainer-flex">
<Dropdown
title="Event Type"
list={this.state.activityIcon}
resetThenSet={this.resetThenSet}
/>
<div>
<input
className="time-input-styling"
type="time"
value={this.state.time}
onChange={this.handleTimeChange}/>
</div>
<div>
<textarea
className="textarea-styling"
/*placeholder="Write summary here"*/
value={this.state.summary}
onChange={this.handleSummaryChange}
cols={60}
rows={3} />
</div>
<div>
<textarea
className="textarea-styling"
/*placeholder="Write notes here"*/
value={this.state.notes}
onChange={this.handleNotesChange}
cols={30}
rows={3} />
</div>
</div>
)
}
}
export default EventContainer;
In the documentation, they alreayd said it:
Refer to the following styling file for overriding the default styles.
You can create your own styling file with the same class names in
order to do your custom styling.
So, you have to create your css file, with the classes and override the classes you want.

Resources