Components are hidden only on page reload(vue js) - javascript

Good evening. With user authorization, two components should be hidden in the header without rebooting (via axios). But they only hide on reboot. With logout operation happens the same thing. What shall I do to take the necessary result?
header.vue
<template>
<li v-if="!user.name" class="nav-item">
<router-link to="/login"><b>Login</b></router-link>
</li>
<hr />
<li v-if="!user.name" class="nav-item">
<router-link to="/signup"><b>Registration</b></router-link>
</li>
</template>
<script>
...
computed: {
token() {
return this.token = localStorage.getItem('token')
}
},
mounted(){
const self = this;
window.axios.defaults.headers.common['Authorization'] = `Bearer ${this.token}`
axios.get('/api/user').then(function (response) {
self.user = response.data
})
.catch(function (error) {
console.log(error);
})
},
methods: {
logout()
{
axios.post('/api/logout').then(() => {
localStorage.removeItem('token')
this.$router.push('/login')
}).catch((errors) => {
console.log(errors)
})
}
}
}
</script>
login.vue
<template>
...
</template>
...
methods: {
loginUser(){
const self = this;
axios.post('/api/login', this.form).then((response) => {
localStorage.setItem('token', response.data)
console.log('logged');
self.$router.push({ name: "CV"});
}).catch((error)=>{
self.validate = error.response.data.errors;
})
}
}
}
</script>

Related

How to fetch and display data on loading and also on search

I would like to fetch and display data on load. After this I would like to display data on search.
Now I only manage to display data on search keyup. I would like to show the list of artist when loading the page as well.
How to display data on load page
How to display data on search
Thanks in advance!
<template>
<div class="body">
<div class="searchBar">
<i class="bi bi-search"></i>
<input
placeholder="Search for artists"
type="text"
v-model="searchQuery"
#keyup="searchArtist"
/>
</div>
<div class="artists">
<div
className="artist__list"
v-for="artistResult in result"
:key="artistResult.id"
>
<h4>{{ artistResult.name }}</h4>
</div>
</div>
</div>
</template>
<script>
import axios from "axios";
import "./body.css";
export default {
data() {
return {
artists: [],
result: [],
searchQuery: "",
};
},
mounted() {
this.fetchArtists();
},
computed: {
filteredResult() {
const res = this.result;
const search = this.searchQuery;
if (!search) {
return res;
}
return res.filter((item) =>
item.name.toLowerCase().includes(search.toLowerCase())
);
},
},
methods: {
searchArtist() {
axios
.get(`http://localhost:3000/artists?q=${this.searchQuery}`)
.then((response) => {
this.result = response.data;
})
.catch((error) => {
console.error(error);
});
},
fetchArtists() {
axios
.get("http://localhost:3000/artists")
.then((response) => {
this.artists = response.data;
})
.catch((error) => {
console.error(error);
});
},
},
};
</script>
On fetch I need it to bind the api response to the empty array result.
return {
result: [],
searchQuery: "",
};
},
fetchArtists() {
axios
.get("http://localhost:3000/artists")
.then((response) => {
this.result = response.data;
})
.catch((error) => {
console.error(error);
});
},

bind a promise to component in Vue

App.vue
<template>
<v-app>
<v-main>
<Header :token="token" :users="users"/>
<router-view/>
</v-main>
</v-app>
</template>
<script>
import Header from './components/layout/Header'
import axios from 'axios';
export default {
name: 'App',
components: {
Header
},
data() {
return { token: null, users: [] };
},
created(){
this.token = this.getToken();
this.users = this.getUsers();
},
methods:{
getToken(){
axios.get("http://someURL.com")
.then(res => {
console.log("token = ", res)
return res;
});
},
getUsers(){
axios.get("http://someURL.com")
.then(res => {
let users = res.data.map(({username}) => username);
console.log("users = ", users)
return users;
});
}
}
};
</script>
Header.vue
<template>
<header class="header">
<v-toolbar dark>
<h1>TITLE</h1>
<v-spacer></v-spacer>
<div>
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</div>
</v-toolbar>
<p v-if="users">{{users}}</p>
<p v-else>No Data</p>
</header>
</template>
<script>
export default {
name:"Header",
props: ['token', 'users'],
data: () => ({
}),
mounted(){
this.onStart();
},
methods:{
onStart(){
console.log("insideHeader = ", this.users)
}
}
}
</script>
<style scoped>
#nav{
float: right;
}
.header a{
color: #fff;
padding-right: 5px;
text-decoration: none;
}
</style>
So basically what my problem is, I am fetching some data on App.vue using axios, then binding that data on Header.vue, So when the app loads first the binded value will be undefined, only after some time the data is fetched from API. But even then the value remains undefined in Header. Any solutions?
Api calls are async in nature. hence make use of async/await..
<template>
<v-app>
<v-main>
<Header :token="token" :users="users"/>
<router-view/>
</v-main>
</v-app>
</template>
<script>
import Header from './components/layout/Header'
import axios from 'axios';
export default {
name: 'App',
components: {
Header
},
data() {
return { token: null, users: [] };
},
async created(){
this.token = await this.getToken();
this.users = await this.getUsers();
},
methods:{
getToken(){
return axios.get("http://someURL.com")
.then(res => {
console.log("token = ", res)
return res.data;
});
},
getUsers(){
return axios.get("http://someURL.com")
.then(res => {
let users = res.data.map(({username}) => username);
console.log("users = ", users)
return users;
});
}
}
};
</script>
Don't try to return a value from promise callback, you could use async/await to return the response :
<template>
<v-app>
<v-main>
<Header :token="token" :users="users"/>
<router-view/>
</v-main>
</v-app>
</template>
<script>
import Header from './components/layout/Header'
import axios from 'axios';
export default {
name: 'App',
components: {
Header
},
data() {
return { token: null, users: [] };
},
created(){
this.token = this.getToken();
this.users = this.getUsers();
},
methods:{
async getToken(){
let res=await axios.get("http://someURL.com")
console.log("token = ", res)
return res.data;
},
async getUsers(){
let res=await axios.get("http://someURL.com")
let users = res.data.map(({username}) => username);
console.log("users = ", users)
return users;
}
}
};
</script>

Error:: Uncaught (in promise) TypeError: Cannot read property "content" of undefined

When writing an application I get the same error as in the title. I create an application in Vue and store the data in the firestore.
The data is sent via this.$store.dispatch ('function'). I get an error in this file on line 47 EditNote.vue
methods: {
editNote() {
this.$store.dispatch('editNote', this.docId, {
content: this.note.content
});
this.note.content = '';
}
})
and I have no idea what it is, maybe some of you can help me. Thank you if any of you could help. 🤞
./src/components/EditNote.vue
<template>
<div class="editnote">
<div class="content">
<div class="content__header">
<h2 class="content__title">
Edytuj notatkę 🐝
</h2>
<span class="content__close" #click="$emit('close')">
<i class="fas fa-times"></i>
</span>
</div>
<div class="content__inside">
<form #submit.prevent>
<textarea
class="content__textarea"
v-model.trim="note.content"
rows="6"
cols="20"
:placeholder="this.noteContent"
></textarea>
<span class="content__plus-icon" #click="editNote"
><i class="fas fa-edit"></i
></span>
</form>
</div>
</div>
</div>
</template>
<script>
import { mapState } from 'vuex';
export default {
props: ['docId', 'noteContent'],
data() {
return {
note: {
content: ''
}
};
},
methods: {
editNote() {
this.$store.dispatch('editNote', this.docId, {
content: this.note.content
});
this.note.content = '';
}
}
};
</script>
./src/store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
import * as fb from '../firebase';
import router from '../router/index';
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
userProfile: {},
notes: []
},
mutations: {
setUserProfile(state, val) {
state.userProfile = val;
},
setNotes(state, val) {
state.notes = val;
}
},
actions: {
async getNotes() {
await fb.usersCollection
.doc(fb.auth.currentUser.uid)
.collection('notes')
.orderBy('createdOn', 'desc')
.onSnapshot(snapshot => {
let notesArray = [];
snapshot.forEach(doc => {
let note = doc.data();
note.id = doc.id;
notesArray.push(note);
});
store.commit('setNotes', notesArray);
});
},
async addNote({}, note) {
await fb.usersCollection
.doc(fb.auth.currentUser.uid)
.collection('notes')
.add({
createdOn: new Date(),
content: note.content,
userId: fb.auth.currentUser.uid
});
},
async editNote({ commit }, docId, note) {
await fb.usersCollection
.doc(fb.auth.currentUser.uid)
.collection('notes')
.doc(docId)
.update({
createdOn: new Date(),
content: note.content
});
},
async deleteNote({}, docId) {
if (window.confirm('Jesteś pewny/a, że chcesz usunąć notatkę?')) {
await fb.usersCollection
.doc(fb.auth.currentUser.uid)
.collection('notes')
.doc(docId)
.delete();
}
},
async signup({ dispatch }, form) {
// sign user up
const { user } = await fb.auth.createUserWithEmailAndPassword(
form.email,
form.password
);
// create user profile object in userCollection
await fb.usersCollection.doc(user.uid).set({
username: form.username,
email: form.email,
password: form.password
});
// fetch user profile and set in state
dispatch('fetchUserProfile', user);
router.push('/login');
},
async login({ dispatch }, form) {
// sign user in
const { user } = await fb.auth.signInWithEmailAndPassword(
form.email,
form.password
);
// fetch user profile and set in state
dispatch('fetchUserProfile', user);
},
async logout({ commit }) {
await fb.auth.signOut();
// clear userProfile and redirect to /login
commit('setUserProfile', {});
router.push('/login');
},
async fetchUserProfile({ commit }, user) {
// fetch user profile
const userProfile = await fb.usersCollection.doc(user.uid).get();
// set user profile in state
commit('setUserProfile', userProfile.data());
// change router to dashboard
if (router.currentRoute.path === '/login') {
router.push('/');
}
}
},
modules: {}
});
export default store;
./src/views/Homepage.vue
<transition
enter-active-class="animate__animated animate__backInUp animate__faster"
leave-active-class="animate__animated animate__backOutDown animate__faster"
mode="out-in"
appear
>
<EditNote
v-if="showEditNote"
#close="toggleEditNote()"
:docId="selectedNote"
:noteContent="selectedNoteContent"
></EditNote>
</transition>
<div class="notes">
<div
class="notes__container-title-icon"
#click="toggleAddNotes"
>
<h3 class="notes__title">Notatki</h3>
<span class="notes__plus-icon">
<i class="fas fa-plus"></i>
</span>
</div>
<ul class="notes__list" v-if="notes.length">
<li
class="notes__item"
v-for="note in notes"
:key="note.id"
>
{{ note.content }}
<br />
<span class="notes__createdOn">{{
getCurrentDate(note.createdOn)
}}</span>
<br />
<div class="notes__extras">
<span
class="notes__edit"
#click="toggleEditNote(note.id, note.content)"
><i class="far fa-edit"></i
></span>
<span
class="notes__delete"
#click="deleteNote(note.id)"
><i class="far fa-trash-alt"></i
></span>
</div>
</li>
</ul>
<ul class="notes__list" style="list-style-type: none" v-else>
<li class="notes__item">
Nie ma żadnej notatki 😢
</li>
</ul>
</div>
</div>
</div>
</template>
<script>
import AddNotes from '#/components/AddNotes';
import EditNote from '#/components/EditNote';
import { mapState } from 'vuex';
export default {
data() {
return {
showAddNotes: false,
showEditNote: false,
selectedNote: '',
selectedNoteContent: '',
};
},
components: {
AddNotes,
EditNote
},
computed: {
...mapState(['userProfile', 'notes']),
},
beforeMount() {
this.getCurrentDate();
},
created() {
this.getNotes();
},
methods: {
toggleEditNote(docId, noteContent) {
this.showEditNote = !this.showEditNote;
if (this.showEditNote) {
this.selectedNote = docId;
this.selectedNoteContent = noteContent;
} else {
this.selectedNote = {};
this.selectedNoteContent = {};
}
},
toggleAddNotes() {
this.showAddNotes = !this.showAddNotes;
},
getNotes() {
this.$store.dispatch('getNotes');
},
deleteNote(docId) {
this.$store.dispatch('deleteNote', docId);
},
The issue is with the editNote action. Actions can only receive one argument so you'll need to pass multiple values as an object or array. Change it to:
async editNote({ commit }, { docId, note }) { // Notice the braces
await fb.usersCollection
.doc(fb.auth.currentUser.uid)
.collection('notes')
.doc(docId)
.update({
createdOn: new Date(),
content: note.content
});
},
And call it in your component this way:
methods: {
editNote() {
const docId = this.docId;
const note = {
content: this.note.content
};
this.$store.dispatch('editNote', { docId, note }); // Notice the braces
this.note.content = '';
}
}

AJAX Search with Laravel and Vue empty Results

i want to build a search with ajax and vue.
So i have a model called "file" here all my files
then i have a controller called searchcontroller.php
public function search(Request $request)
{
$files = File::where('name', $request->keywords)->get();
return response()->json($files);
}
this is my route
Route::post('/', 'SearchController#search');
and i have a search.vue
<template>
<div>
<input type="text" v-model="keywords">
<ul v-if="results.length > 0">
<li v-for="result in results" :key="result.id" v-text="result.name"></li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
keywords: null,
results: []
};
},
watch: {
keywords(after, before) {
this.fetch();
}
},
methods: {
fetch() {
axios.get('/', { params: { keywords: this.keywords } })
.then(response => this.results = response.data)
.catch(error => {});
}
}
}
</script>
if i type a letter the resposce work i think but it shows me 10000 list points with an emtpy result
i wanna do it like here: https://jsfiddle.net/hej7L1jy/2/
if i do:
console.log(this.results);
console.log(this.keywords);
i get for results:
Array(0)
and the keyword works
public function search(Request $request)
{
$files = File::where('name', 'like', '%' . $request->get('keywords') . '%')->get();
return response()->json($files);
}
<template>
<div>
<input type="text" v-model="keywords">
<ul v-if="results.length > 0">
<li v-for="result in results" :key="result.id">{{ result.name }}</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
keywords: null,
results: []
};
},
watch: {
keywords(after, before) {
this.fetch();
}
},
methods: {
fetch() {
axios.post('/', { params: { keywords: this.keywords } })
.then(response => this.results = response.data)
.catch(error => {});
}
}
}
</script>
I GOT IT :)
Controller:
public function search(Request $request)
{
$files = DB::table('files')->where('name', 'like', '%' . $request->get('keywords') . '%')->get();
return response()->json($files);
}
Route:
Route::get('/search', 'SearchController#search');
Vue:
<template>
<div>
<input type="text" v-model="keywords">
<ul v-if="results.length > 0">
<li v-for="result in results" :key="result.id">{{ result.name }}</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
keywords: null,
results: []
};
},
watch: {
keywords(after, before) {
this.fetch();
}
},
methods: {
fetch() {
axios.get('/search', { params: { keywords: this.keywords } })
.then(response => this.results = response.data)
.catch(error => {});
}
}
}
</script>
i edited the where function in my controller and i needed a "get" method , not a "post" :)

Ruby on Rails and React/Redux, Uncaught TypeError: (0 , _tasks.getTask) is not a function

I want to make a transition from a link to an article, to the article itself, when I click on a link, the construction is triggered: Not found. Tell me what I'm doing wrong.
task_conteiner.js
import React, { Component } from 'react';
import { browserHistory } from 'react-router';
import { Link } from 'react-router';
export default class TasksContainer extends Component {
onShowMoreTask(id) {
browserHistory.push(`#/tasks/${id}`);
location.reload()
}
renderTasks() {
let filterComleted = this.props.tasks.tasks
let str = '★'
let style
if (this.props.Completed === "task.completed") {
filterComleted = filterComleted.filter(task => task.completed);
} else {
filterComleted = filterComleted.filter(task => !task.completed);
}
return filterComleted.map((task) => {
if(task.completed){
style = {
textDecoration: 'line-through'
}
}
return (
<div key={task.id}>
<li className="todo">
<div className="container">
<div className="col-md-3" onClick={() => this.onShowMoreTask( task.id )}>{ task.title }</div>
<div className="col-md-3" style={style}>{ task.description }</div>
<div className="col-md-3" style={style}>{ task.due_date }</div>
<div className="col-md-1 star">{ str.repeat(task.priority) }</div>
<span onClick={() => this.props.onCompletedTask(task.id, task.completed)} className={task.completed ? "glyphicon glyphicon-repeat" : "glyphicon glyphicon-ok"} title={task.active ? "Mark active" : "Mark completed"}></span>
<span onClick={() => this.props.onEditTask( this.props.editId, task.id )} className="glyphicon glyphicon-pencil" title="Edit task"></span>
<span onClick={() => this.props.onDeleteTask(task.id)} className="glyphicon glyphicon-trash" title="Delete"></span>
</div>
</li>
</div>
);
});
}
render() {
return (
<div>
{this.renderTasks()}
</div>
);
}
}
task_details.js
import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import Exit from '../authentication/exit';
import { browserHistory } from 'react-router';
import { getTask } from '../../actions/tasks';
import TasksList from './tasks_list';
import '../../index.css';
import Link from 'react-router'
class TaskDetails extends Component {
componentDidMount () {
let id = this.props.params.id;
this.props.onGetTask(id);
};
render() {
const { task } = this.props
console.log(this.props.location.pathname, "xxxxxxxx")
return (
<div>
{ this.props.task ?
<div className="container">
<h2 className="text-center">{task.title}</h2>
<div className="col-md-2">
<h4 className="pull-right"><i>{task.due_date}</i></h4>
</div>
<div className="clearfix"></div>
<div className="description">
<p>{task.description}</p>
</div>
</div>
:
<div className="container">
<div><h2>Not found</h2></div>
</div>
}
</div>
);
}
};
export default connect(
state => ({
task: state.tasks.item
}),
dispatch => ({
onGetTask: (id) => {
dispatch(getTask(id));
},
})
)(TaskDetails);
The task_details triggers the construction:
<div className="container">
<div><h2>Not found</h2></div>
</div>
There is an error in the console:
/tasks/6 xxxxxxxx
task_details.js:50 Uncaught TypeError: (0 , _tasks.getTask) is not a function
at Object.onGetTask (task_details.js:50)
at TaskDetails.componentDidMount (task_details.js:14)
at ReactCompositeComponent.js:265
at measureLifeCyclePerf (ReactCompositeComponent.js:75)
at ReactCompositeComponent.js:264
at CallbackQueue.notifyAll (CallbackQueue.js:76)
at ReactReconcileTransaction.close (ReactReconcileTransaction.js:80)
at ReactReconcileTransaction.closeAll (Transaction.js:206)
at ReactReconcileTransaction.perform (Transaction.js:153)
at batchedMountComponentIntoNode (ReactMount.js:126)
Thank you for your help.
and
reducers/task.js
export default function tasks(state = {
tasks: [],
edit: '',
sortBy: {title: "priority", asc: "desc"}
}, action) {
switch (action.type) {
case "FETCH_TODOS_SUCCESS":
return {
...state,
tasks: action.payload
};
case "GET_TASKS":
return {
...state,
tasks: action.payload
}
case "ADD_TASK":
return {
...state,
tasks: [action.payload, ...state.tasks]
}
case "DELETE_TASK":
state.tasks = state.tasks.filter(t => t.id !== action.payload);
return {
...state,
tasks: [...state.tasks]
}
case "EDIT_TASK":
state.tasks = state.tasks.filter(t => t.id !== action.payload.id);
return {
...state,
tasks: [action.payload, ...state.tasks]
}
case "COMPLITED_TASK":
state.tasks = state.tasks.filter(t => t.id !== action.payload.id);
return {
...state,
tasks: [action.payload, ...state.tasks]
};
case "EDIT_ID":
return {
...state,
edit: action.payload
}
case "SORT_BY":
return {
...state,
sortBy: action.payload
}
default:
return state;
}
}
action/task.js
import axios from 'axios';
import cookie from 'react-cookies';
//const API_URL = `https://evening-taiga-79121.herokuapp.com/todos`;
const API_URL = `http://localhost:3000/todos`;
let headers = { 'Content-Type': 'application/json', };
const token = cookie.load('token');
export function fetchTasks(user_id){
return function(dispatch, getState) {
let body = JSON.stringify({ token: token });
headers['Authorization'] = `Bearer ${token}`;
axios.get(`${API_URL}`, { headers, body })
.then(res => {
if (res.status === 200) {
dispatch({ type: 'GET_TASKS', payload: res.data });
}
})
.catch(e => {
console.error("error: ", e);
})
}
}
export function deleteTask(id){
return function(dispatch, getState) {
let body = { token: token };
axios.delete(`${API_URL}/${id}`, { params: body, headers: headers })
.then(res => {
dispatch({ type: 'DELETE_TASK', payload: id });
})
.catch(id => {
console.error("error", id);
})
}
}
export function addTask(task){
return function(dispatch, getState) {
let body = JSON.stringify({todo: task, token: token});
console.log(body);
axios.post(API_URL, body, { headers: headers })
.then(res => {
dispatch({ type: 'ADD_TASK', payload: res.data });
})
.catch(e => {
console.error(e);
})
}
}
export function completedTask(id, complete){
return function(dispatch, getState) {
if (complete === true) {
complete = false
} else {
complete = true
}
let task = {id: id, completed: complete};
let body = {todo: task, token: token};
axios.patch(`${API_URL}/${task.id}`, body, { headers: headers })
.then(res => {
dispatch({ type: 'COMPLITED_TASK', payload: res.data });
})
.catch(e => {
console.error("error: ", e);
})
}
}
export function sortTasks(sortBy){
return function(dispatch, getState) {
let body = JSON.stringify({ token: token, sortByTitle: sortBy.title, sortByAsc: sortBy.asc });
axios.post(`${API_URL}/sort`, body, { headers: headers })
.then(res => {
console.log(res);
if (res.status === 200) {
dispatch({ type: 'SORT_BY', payload: sortBy });
dispatch({ type: 'FETCH_TODOS_SUCCESS', payload: res.data });
}
})
.catch(e => {
console.error("error: ", e);
})
}
}
export function editTask(task){
return function(dispatch, getState) {
let body = JSON.stringify({todo: task, token: token});
axios.patch(`${API_URL}/${task.id}`, body, { headers: headers })
.then(res => {
dispatch({ type: 'EDIT_TASK', payload: res.data });
})
.catch(e => {
console.error("error: ", e);
})
}
}

Categories

Resources