I am converting my angular 11 project to angular 12 and there are some problem I am facing. In one component which is ngx-nestable its working fine in angular 11 but as I have updated it to version 12 it's showing me some error please check screen shot.
This is my .ts file code:
import { Component, OnInit, ElementRef, Renderer2 } from '#angular/core';
import { NestableSettings } from './lib/nestable.models';
#Component({
selector: 'app-nestable',
templateUrl: './nestable.component.html',
styleUrls: ['./nestable.component.css']
})
export class NestableComponent implements OnInit {
public idCount = 13;
public options = {
fixedDepth: false
} as NestableSettings;
public list = [
{ 'id': 1 },
{
'expanded': true,
'id': 2, 'children': [
{ 'id': 3 },
{ 'id': 4 },
{
'expanded': false,
'id': 5, 'children': [
{ 'id': 6 },
{ 'id': 7 },
{ 'id': 8 }
]
},
{ 'id': 9 },
{ 'id': 10 }
]
},
{ 'id': 11 },
{
'id': 12,
'children': [
{ 'id': 13 }
]
},
{ 'id': 14 },
{ 'id': 15 }
];
constructor(
private el: ElementRef,
private renderer: Renderer2
) {
this.renderer.listen(this.el.nativeElement, 'listUpdated', e => {
this.list = e.detail.list;
});
}
public pushItem() {
this.list.push({ id: ++this.idCount });
this.list = [...this.list];
}
public toggleFixedDepth() {
this.options.fixedDepth = !this.options.fixedDepth;
}
public drag(e: any) {
console.log(e);
}
public drop(e: any) {
console.log(e);
}
public onDisclosure(e: any) {
console.log(e);
}
ngOnInit(): void {
}
}
and this is my html code
<ngx-nestable class="ngx-nestable col-lg-6"
(drag)="drag($event)"
(drop)="drop($event)"
(disclosure)="onDisclosure($event)"
[(list)]="list"
#nestable
[options]="options"
[template]="itemTemplate"
fxFlex="50">
</ngx-nestable>
<ng-template #itemTemplate let-row>
<button mat-icon-button [ngxNestableDragHandle]="row">
<mat-icon>drag_handle</mat-icon>
</button>
<button mat-icon-button *ngIf="row.item.children && row.item.children.length; else empty_item" [ngxNestableExpandCollapse]="row">
<mat-icon>{{row.item.$$expanded ? 'keyboard_arrow_down' : 'keyboard_arrow_right'}}</mat-icon>
</button>
<div>Item: {{row.item.id}}</div>
</ng-template>
Please tell me what should I change or add in the code file so that it will start working. I am trying to find a solution for many days but to no avail.
Thanks
This problem is resolved by just adding the below code in template file check screenshot
Thanks
Related
I m using vis.js timeline and i want display date from firestore. It works when I type manually (look --> this.items), but does not work with firestore (look --> this.users).
I m using Vue framework.
<script>
export default {
data() {
return {
users: [],
items: [
{
id: '1',
content: 'London',
group: 'Mike',
start: '2021-12-20',
end: '2022-06-19',
},
],
}
},
async fetch() {
await this.loadPlaces()
},
methods: {
async loadPlaces() {
const querySnapshot = await getDocs(collection(db, 'places'))
querySnapshot.forEach((doc) => {
this.users.push({ id: doc.id, ...doc.data() })
})
this.$store.commit('places/setPlaces', this.users)
},
},
computed: {
places() {
return this.$store.state.places.places
},
},
mounted() {
let container = document.getElementById('visualization')
let options = {
moveable: true,
}
let timeline = new vis.Timeline(container)
timeline.setOptions(options)
timeline.setGroups(this.groups)
timeline.setItems(this.items)
},
}
</script>
I found a solution.
I just moved all code from mounted() to method loadPlaces (under this.$store.commit)
Save yourself trouble and use the vis datasets instead.
my pinia store in vue 3 looks like this.
import { defineStore } from 'pinia'
import { DataSet } from 'vis-data/esnext'
export const useVisData = defineStore('visData', {
state: () => ({
items: new DataSet([]),
groups: new DataSet([]),
selectedItems: [],
serializedGroupsAndItems: []
}),
actions: {
//Group actions
showAllGroups() {
this.groups.forEach(group => {
this.groups.updateOnly({ id: group.id, visible: true })
});
},
addGroup(group) {
this.groups.add(group)
},
hideGroup(group) {
this.groups.updateOnly({ id: group, visible: false })
},
//Item actions
addItem(item) {
this.items.add(item)
},
removeItem(item) {
this.items.remove(item)
},
setSelectedItems(items) {
this.selectedItems = items
},
//data add/remove
serializeData() {
this.serializedGroupsAndItems.push({
groups: JSON.stringify(this.groups.get()),
items: JSON.stringify(this.items.get())
})
},
loadSerializedData() {
this.clearGroupsAndItems()
this.serializedGroupsAndItems.forEach(data => {
this.addGroup(JSON.parse([data.groups]))
this.addItem(JSON.parse([data.items]))
})
},
//misc
clearGroupsAndItems() {
this.groups.clear()
this.items.clear()
}
},
getters: {
getHiddenGroups(state) {
return state.groups.get({
filter: (item) => {
return item.visible === false
}
})
}
}
})
Also remember to watch for changes in your options.
Might be better to wrap it in a vue component too. something like this.
this is what i did.
let timeline;
const visref = ref(null);
onMounted(async () => {
timeline = new Timeline(visref.value, props.items, props.groups, {...props.options, ...timelineOptions});
props.events.forEach(event => {
on(event, (properties) => {
// console.log(event, properties)
emits(`vis${event}`, properties);
});
});
})
<template>
<div ref="visref"></div>
</template>
then you can use it like so:
const timelineref = ref();
<Timeline
ref="timelineref"
:items="visStore.items"
:groups="visStore.groups"
:options="options"
/>
remember to expose the instance in your timeline component then you can call the functions using a ref like this.
timelineref.value.timeline.zoomOut(0.5)
I have some data in a firestore and want to display it in my vue app.
Firestore:
Test.vue
<template>
<p>{{ items }}</p>
</template>
<script>
import { mapState } from "vuex";
export default {
computed: mapState(["items"]),
methods: {
getItems() {
this.$store.dispatch("bindItems");
},
},
mounted() {
this.getItems();
},
};
</script>
index.js
import { createStore } from "vuex";
import { firestoreAction } from "vuexfire";
import { vuexfireMutations } from "vuexfire";
import { db } from "./db";
const store = createStore({
state() {
return {
items: [],
};
},
actions: {
bindItems: firestoreAction(({ bindFirestoreRef }) => {
return bindFirestoreRef("items", db.collection("items"));
}),
},
mutations: {
...vuexfireMutations,
},
getters: {
items(state) {
return state.items;
},
},
});
store.subscribe((state) => console.log(state));
export default store;
To check my store, I added this line in index.js: store.subscribe((state) => console.log(state));. As it turns out, the data from firestore actually makes it to my store:
Why is it not rendered in the frontend? What do I have to change to make it appear?
Edit.
When I hardcode some data in my store and remove this.$store.dispatch("bisndItems"); from the monuted hook, the data gets rendered:
state() {
return {
items: {"name": "peter"},
};
},
Okay so i am fairly new at ionic and i am experiencing this problem where by i am getting the users data from firebase but whenever i set it to the public variable and try and reference it in the html file, i am getting a log error of "cannot set 'variable name' to property of undefined". Here is my code for a more clearer explanation and understanding of what i am trying to achieve. Thank you.
.ts file:
import { Component } from '#angular/core';
import { IonicPage, NavController, NavParams,AlertController,
LoadingController, Loading } from 'ionic-angular';
import {AngularFireAuth} from 'angularfire2/auth';
import { MenuPage } from '../menu/menu';
import firebase from 'firebase';
import { first } from 'rxjs/operators';
#IonicPage()
#Component({
selector: 'page-account',
templateUrl: 'account.html',
})
export class AccountPage {
public userinfo;
constructor(public navCtrl: NavController, public navParams: NavParams,
private alertCtrl:AlertController, public fAuth:AngularFireAuth,
public loading:LoadingController) {
}
ionViewDidLoad() {
console.log('ionViewDidLoad AccountPage');
this.readData();
}
isLoggedIn(){
return this.fAuth.authState.pipe(first()).toPromise();
}
userStatus(){
const user = this.isLoggedIn()
if(user){
console.log('logged in');
this.readData();
}else{
}
}
async readData(){
let load = this.loading.create({
content: "Setting up your profile...",
spinner:'dots'
});
load.present();
await this.fAuth.authState.subscribe((user:firebase.User) =>{
if(user){
firebase.database().ref('/users/' +
user.uid).once('value').then(function(snapshot){
if(snapshot.exists()){
var data = (snapshot.val() && snapshot.val().username) ||
'Anonymous';
//this.userinfo = data;
console.log(data);
}else{
console.log("i need a name");
}});
}else{
console.log("not logged in, log in please");
this.alertLogin();
};
});
console.log(this.userinfo );
load.dismiss();
}
getName(){
let alert = this.alertCtrl.create({
title: 'Hello new friend! :) please can you tell us your name...',
inputs: [
{
name: 'name',
placeholder: 'name'
}
],
buttons: [
{
text: 'Cancel',
role: 'cancel',
handler: data => {
console.log('Cancel clicked');
this.navCtrl.setRoot(MenuPage);
}
},
{
text: 'Confirm',
handler: data => {
this.fAuth.authState.subscribe((user:firebase.User) =>{
firebase.database().ref('/users/' + user.uid).set({
username:data.name
});
});
}
}
]
});
alert.present();
}
alertLogin(){
//if user is not already logged in
let alert = this.alertCtrl.create({
title: 'Whoa there Sally! you need to log in first! :)',
inputs: [
{
name: 'email',
placeholder: 'email'
},
{
name: 'password',
placeholder: 'Password',
type: 'password'
}
],
buttons: [
{
text: 'Cancel',
role: 'cancel',
handler: data => {
console.log('Cancel clicked');
this.navCtrl.setRoot(MenuPage);
}
},
{
text: 'Login',
handler: data => {
this.login(data.email,data.password);
}
},{
text: 'Register',
handler: data => {
this.register(data.email,data.password);
}
}
]
});
alert.present();
}
async login(email,password){
try{
var login = await this.fAuth.auth.signInWithEmailAndPassword(
email,
password
);
if(login){
console.log("Successfully logged in!");
}
}catch(err){
console.error(err);
alert("Sorry we couldnt find you in our system :(");
this.navCtrl.setRoot(MenuPage);
}
}
async register(email,password){
try{
var reg = await this.fAuth.auth.createUserWithEmailAndPassword(
email,
password
);
if(reg){
this.getName();
console.log("successfully registered!");
this.navCtrl.setRoot(AccountPage);
}
}catch(err){
console.error(err);
}
}
logout(){
this.fAuth.auth.signOut();
}
}
.html file:
<ion-item>
<h1>{{userinfo}}</h1>
</ion-item>
Okay so i have tried basically everything and have decided to rather just upload the name to the database and write it locally in the storage of the application. I will just pull the name, along with further details later on in the application process. However if anyone finds an answer for this post, i would greatly appreciate it!
how can i access the doctor attribute from my doctor component ?
Vue.component('specialists', {
template: `
<div>
<div class="list-group-item title">
» {{ name }}
</div>
<doctor class="list-group-item" v-for="doctor in doctors">
<a href="#" class="list-group-item-heading">
{{ doctor.full_name }}
</a>
</doctor>
</div>
`,
props: {
name: {
default: '',
},
},
data: function() {
return {
algoliaClient: null,
algoliaIndex: null,
doctors: [],
};
},
created: function() {
this.algoliaClient = this.$parent.algoliaClient;
this.algoliaIndex = this.algoliaClient.initIndex('medical_doctors');
},
mounted: function() {
this.getDoctors();
},
methods: {
getDoctors: function() {
this.search(this.name);
},
search: function(input) {
var _this = this;
this.algoliaIndex.search(this.name, function(err, hits) {
_this.setDoctors(hits.hits);
});
},
setDoctors: function(data) {
this.doctors = data;
},
},
});
// my doctor component
Vue.component('doctor', {
template: `
<div><slot></slot></div>
`,
data: function() {
return {
doctor: null, // here. how can i pass value to it?
};
},
});
How can i access the doctor attribute from my specialists component ?
I've tried accessing the this.$children from specialists component but the child is null
I'd try something like this :
Vue.component('specialists', {
template: `
<div>
<div class="list-group-item title">
» {{ name }}
</div>
<doctor class="list-group-item" v-for="doctor in doctors" :doctor="doctor">
<a href="#" class="list-group-item-heading">
{{ doctor.full_name }}
</a>
</doctor>
</div>
`,
props: {
name: {
default: '',
},
},
data: function() {
return {
algoliaClient: null,
algoliaIndex: null,
doctors: [],
};
},
created: function() {
this.algoliaClient = this.$parent.algoliaClient;
this.algoliaIndex = this.algoliaClient.initIndex('medical_doctors');
},
mounted: function() {
this.getDoctors();
},
methods: {
getDoctors: function() {
this.search(this.name);
},
search: function(input) {
var _this = this;
this.algoliaIndex.search(this.name, function(err, hits) {
_this.setDoctors(hits.hits);
});
},
setDoctors: function(data) {
this.doctors = data;
},
},
});
// my doctor component
Vue.component('doctor', {
template: `
<div><slot></slot></div>
`,
props: {
doctor: {
default: '',
}
}
});
passing :doctor="doctor" in the for loop of the parent
and adding doctor to props in the child component
props: {
doctor: {
default: '',
},
},
I am working with Vuex and Firebase Auth system.
I just want to store with Vuex the user object that i get from:
firebase.auth().getCurrentUser
so that every time it changes, it updates the views.
But i ve troubles with this.
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
user: {
loggedIn: false,
data: null
}
},
getters: {
user(state){
return state.user
}
},
mutations: {
SET_LOGGED_IN(state, value) {
state.user.loggedIn = value;
},
SET_USER(state, data) {
state.user.data = data;
}
},
actions: {
fetchUser({ commit }, user) {
commit("SET_LOGGED_IN", user !== null);
if (user) {
commit("SET_USER", user);
} else {
commit("SET_USER", null);
}
}
}
});
Account.vue
<template>
<ion-item>
<ion-label #click="openModal()" position="stacked">Your name</ion-label>
{{user.data.displayName}}
</ion-item>
</template>
computed: {
// map `this.user` to `this.$store.getters.user`
...mapGetters({
user: "user"
})
},
methods: {
openModal() {
let us = this.$store.getters.user;
return this.$ionic.modalController
.create({
component: Modal,
componentProps: {
data: {
content: 'New Content',
},
propsData: {
pro: us.data.displayName
},
},
})
.then(m => m.present())
},
.
.
.
</script>
Modal.vue
<template>
<ion-app>
<h1>MODAL</h1>
<ion-input :value="prop" #input="prop = $event.target.value"></ion-input>
<ion-button #click="clos()">Save</ion-button>
</ion-app>
</template>
<script>
import firebase from "firebase";
export default {
props:['pro'],
data(){
return{
prop: this.pro
}
},
methods:{
clos(){
let vm = this;
let user = firebase.auth().currentUser;
window.console.log("updating",vm.prop)
user.updateProfile({
displayName: vm.prop
}).then(function(){
user = firebase.auth().currentUser;
vm.$store.dispatch("fetchUser",user);
}).catch(function(err){
window.console.log("err",err);
})
this.$ionic.modalController.dismiss();
}
}
}
</script>
I can see using Vue Dev Tools that when I dispatch the new user in Modal.vue
vm.$store.dispatch("fetchUser",user);
that the Vuex state is correctly updated, but the view in Account.vue is not.
But if I press the button 'commit this mutation' in the dev tools the view updates!
How can I fix this behavior?
try this solution:
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
user: {
loggedIn: false,
data: null
}
},
getters: {
user(state){
return state.user;
},
userData(state){
return state.user.data;
}
},
mutations: {
SET_LOGGED_IN(state, value) {
state.user.loggedIn = value;
},
SET_USER(state, data) {
state.user.data = data;
}
},
actions: {
fetchUser({ commit }, user) {
commit("SET_LOGGED_IN", user !== null);
if (user) {
commit("SET_USER", user);
} else {
commit("SET_USER", null);
}
}
}
});
Account.vue
<template>
<ion-item>
<ion-label #click="openModal()" position="stacked">Your name</ion-label>
{{user.displayName}}
</ion-item>
</template>
computed: {
// map `this.user` to `this.$store.getters.user`
...mapGetters({
user: "userData"
})
},
methods: {
openModal() {
let us = this.$store.getters.userData;
return this.$ionic.modalController
.create({
component: Modal,
componentProps: {
data: {
content: 'New Content',
},
propsData: {
pro: us.displayName
},
},
})
.then(m => m.present())
},
.
.
.
</script>
You can try this:
SET_USER(state, data) {
Vue.$set(state.user, 'data', data)
}