link137 link138 link139 link140 link141 link142 link143 link144 link145 link146 link147 link148 link149 link150 link151 link152 link153 link154 link155 link156 link157 link158 link159 link160 link161 link162 link163 link164 link165 link166 link167 link168 link169 link170 link171 link172 link173 link174 link175 link176 link177 link178 link179 link180 link181 link182 link183 link184 link185 link186 link187 link188 link189 link190 link191 link192 link193 link194 link195 link196 link197 link198 link199 link200 link201 link202 link203 link204 link205 link206 link207 link208 link209 link210 link211 link212 link213 link214 link215 link216 link217 link218 link219 link220 link221 link222 link223 link224 link225 link226 link227 link228 link229 link230 link231 link232 link233 link234 link235 link236 link237 link238 link239 link240 link241 link242 link243 link244 link245 link246 link247 link248 link249 link250 link251 link252 link253 link254 link255 link256 link257 link258 link259 link260 link261 link262 link263 link264 link265 link266 link267 link268 link269 link270 link271 link272 link273

[Vue.js] Await a grandparent component's method to be resolved in grandchild component Subscribe to RSS

there is three components in my vue.js application:

Home: (Button’s grandparent)
Dialog: (Home’s child / Button’s parent)
Button: (Home’s grandchild)

The Home component has a async method:

async handleDialogAccept() {
try {
const response = await this.$axios.get(‘https://jsonplaceholder.typicode.com/todos/');
console.log(response.data);
} catch (err) {
console.log(err);
}
},

And it will executed as soon as the Dialog component emits the “accept” custom event:

<dialog-confirmation
@accept=”handleDialogAccept()”
/>

The Dialog component has a child (Button):

<button-accept
v-on=”$listeners”
\>
Accept
</button-accept>

In my buttonAccept.vue.js which is being imported in the Dialog and used as shown above has the next structure:

<template>
<v-btn
color=”primary”
@click=”handleClick()”
:loading=”loading”
:disabled=”loading”
\>
<slot name=”accept”></slot>
</v-btn>
</template>

<script>
export default {
props: [‘parentFunction’],
data() {
return {
loading: false,
};
},
methods: {
handleClick() {
this.$emit(‘accept’);
},
},
};
</script>

I will like to execute the next steps inside the handleClick method:

Set loading to true
Emit the accept custom event
Wait until the handleDialogAccept is done
Set loading to false

Is there a wait to do so?

Solution :

Maybe, you can define a variable (isAcceptDone) in Home component to determine whether the async method is done or not in the Button component.

The Home component

async handleDialogAccept() {
try {
const response = await this.$axios.get(‘https://jsonplaceholder.typicode.com/todos/');
console.log(response.data);
this.isAcceptDone = true;
} catch (err) {
console.log(err);
}
},

The Dialog component

<dialog-confirmation
@accept=”handleDialogAccept()”
:isAcceptDone=”isAcceptDone”
/>

The Button component

<script>
export default {
props: [‘parentFunction’, ‘isAcceptDone’],
data() {
return {
loading: false,
};
},
watch: {
isAcceptDone(val) {
if(val) {
this.loading = false
}
}
},
methods: {
handleClick() {
this.$emit(‘accept’);
},
}
};
</script>

On the other hand, If you thought it is too complicated to pass isAcceptDone in three components. Using EventBus is another simple ways.

[Vue.js] How to focus Quill editor using the vue-quill package? Subscribe to RSS

when using the vue-quill-editor package for my vue.js application, but I can only focus on the editor if I click on the same line as the editor.
I would like to be able to focus on the Editor by clicking anywhere within the parent

I know there is a quill.focus() function, but is there a way that I can access it without changing the vue-quill-editor file?
If I do change it, are there things that I should be aware of when working with others?

https://imgur.com/a/mhKPVo0
here there is uploaded a photo that may better explain my struggle.

Any suggestions on what I should try?

Solution :

Listen to the parent clicks an then find the quill editor (by id or by any selector) then element.focus()
BTW, the element has to be an input element.

[Vue.js] how to know when dynamic component has fully loaded Subscribe to RSS

So I’m loading some components dynamically like so:

const Page0 = () => import(“@/components/pages/tutorial/Pages/Page0”)
const Page1 = () => import(“@/components/pages/tutorial/Pages/Page1”)

There are 10 more pages like this, which will be called depending on the route params.

I was wondering how I would know if a certain Page was loaded, for the purposes of creating a loading screen, and how I would know when it was being switched.

This is how I’m using it altogether.

<template>
<div>
<component :is=”current_page”></component>
</div>
</template>

<script>
const Page0 = () => import(“@/components/pages/tutorial/Pages/Page0/index.vue”)
const Page1 = () => import(“@/components/pages/tutorial/Pages/Page1/index.vue”)

export default {
scrollToTop:
true,
components:
{
Page0,
Page1,
},
computed:
{
current_page ()
{
return “Page” + this.page
}
},
asyncData ({
route, store, env, params, query, req, res, redirect, error
})
{
return {
page:
params.page
}
}
}
</script>

Solution :

how to know when dynamic component has fully loaded ?

You can use @hook:mounted for every component dynamic or not to indicate that the component is loaded.

e.g.

<component :is=”current_page” @hook:mounted=”doSomething”></component>

Check codesandbox example

[Vue.js] How can I use Vue.js with json array - simple example Subscribe to RSS

there is been searching for hours for a simple example on this, so I’ve come to the SO community for help.

If there is a json object (external, let’s say we’ve accessed it as “Info”) with arrays like this…

{
“Job”: {
“JobId”: “123”,
“Tasks”: [
{
“TaskId”: “1”,
“TaskName”: “Test Task 1”,
“SubTasks”: [
{
“SubTaskId”: “1”,
“SubTaskName”: “Test Sub Task 1”
},
{
“SubTaskId”: “2”,
“SubTaskName”: “Test Sub Task 2”
},
{
“SubTaskId”: “3”,
“SubTaskName”: “Test Sub Task 3”
}
]
},
{
“TaskId”: “2”,
“TaskName”: “Test Task 2”,
“SubTasks”: [
{
“SubTaskId”: “1”,
“SubTaskName”: “Test Sub Task 1”
},
{
“SubTaskId”: “2”,
“SubTaskName”: “Test Sub Task 2”
},
{
“SubTaskId”: “3”,
“SubTaskName”: “Test Sub Task 3”
}
]
},
{
“TaskId”: “3”,
“TaskName”: “Test Task 3”,
“SubTasks”: [
{
“SubTaskId”: “1”,
“SubTaskName”: “Test Sub Task 1”
},
{
“SubTaskId”: “2”,
“SubTaskName”: “Test Sub Task 2”
},
{
“SubTaskId”: “3”,
“SubTaskName”: “Test Sub Task 3”
}
]
}
]
}
}

How do I access that in a vue.js instance and access the nested arrays? Every example I can find is either woefully over my head, or looks like the following:

new Vue({
el: “ID1”,
data: {
items: [
{ message: ‘Foo’ },
{ message: ‘Bar’ }
]
}
})

However I already know how to use v-for to get data from an array that’s already in the instance (hardcoded in I mean), though the nested arrays still escape me a little, but I can’t for the life of me figure out a straightforward way to get the access to the arrays and nested arrays if they are in a json object w/arrays.

I’ve tried just putting “Data” in the instance as follows to get the object:

new Vue({
el: “ID1”,
data: Info
})

or

new Vue({
el: “ID1”,
data: {
items: Info,
/// extra stuff here
}
})

It works as far as I can access the object (Info), but I run into an error when trying to use something like v-for=”Task in Tasks” (as an example) “Property or method “Tasks” is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for classed-based components, by initializing the property”.

I’d like to be able to do:

<div id=”ID1”>
<ul>
<li v-for=”Task in Tasks”>{ Task.TaskId }</li>
</ul>
</div>

or further:

<div id=”ID1”>
<ul>
<li v-for=”SubTask in SubTasks”>{ SubTask.SubTaskId }</li>
</ul>
</div>

I know those don’t work, just want to give an example.

Any help would be wildly appreciated on this. Feel free to take me to vue.js 101. I’m not sure what else to ask or what to provide to make it a better question. I would normally not ask a question this broad, I would normally take the time to actually learn how to do this but when stuck and trying to get some things done for tomorrow and pretty frustrated at this point. I’ve used nested forEach loops in JS and output with JQuery tons of times but I just can’t figure out this logic in Vue. Thanks in advance.

Solution :

If you add it to the data like this…

data: {
items: Info
}

… then you’d access it as items within the template.

As the data has some nesting the tasks would be available as items.Job.Tasks. Here the . for accessing properties works just like it would in any other JavaScript context. Similarly the square bracket notation is also available should you need it.

So something like v-for=”task in items.Job.Tasks” would create a loop over the tasks and a local variable called task would be created for each item. This is just like when you’re using forEach to loop over an array, e.g. items.Job.Tasks.forEach(task => {…}).

To get at the sub-tasks you’d then use v-for=”subTask in task.SubTasks”.

A complete example:

const Info = {
“Job”: {
“JobId”: “123”,
“Tasks”: [{
“TaskId”: “1”,
“TaskName”: “Test Task 1”,
“SubTasks”: [{
“SubTaskId”: “1”,
“SubTaskName”: “Test Sub Task 1”
},
{
“SubTaskId”: “2”,
“SubTaskName”: “Test Sub Task 2”
},
{
“SubTaskId”: “3”,
“SubTaskName”: “Test Sub Task 3”
}
]
},
{
“TaskId”: “2”,
“TaskName”: “Test Task 2”,
“SubTasks”: [{
“SubTaskId”: “1”,
“SubTaskName”: “Test Sub Task 1”
},
{
“SubTaskId”: “2”,
“SubTaskName”: “Test Sub Task 2”
},
{
“SubTaskId”: “3”,
“SubTaskName”: “Test Sub Task 3”
}
]
},
{
“TaskId”: “3”,
“TaskName”: “Test Task 3”,
“SubTasks”: [{
“SubTaskId”: “1”,
“SubTaskName”: “Test Sub Task 1”
},
{
“SubTaskId”: “2”,
“SubTaskName”: “Test Sub Task 2”
},
{
“SubTaskId”: “3”,
“SubTaskName”: “Test Sub Task 3”
}
]
}
]
}
}

new Vue({
el: “#ID1”,
data: {
items: Info
}
})
<script src=”https://unpkg.com/vue@2.6.10/dist/vue.js"></script>
<div id=”ID1”>
<ul>
<li v-for=”task in items.Job.Tasks”>
{ task.TaskId } - { task.TaskName }
<ul>
<li v-for=”subTask in task.SubTasks”>
{ subTask.SubTaskId } - { subTask.SubTaskName }
</li>
</ul>
</li>
</ul>
</div>

[Vue.js] LARAVEL & VUE How can I get the API_TOKEN of the logged in user with an API request? Subscribe to RSS

there is a SPA using vue.js and LARAVEL 5.8
there is setup an API_TOKEN associated to the logged in user. Everything works fine right after the login. I get the API_TOKEN, I save it into a var and I send it together with the Axios request. In Laravel there is a middleware that is taking care of the token and comparing it with the one setup on the logged in user.

the problem though occur when session expires. Because I still can navigate the private pages and make API requests to save and delete content. This is possible I think because I still have the same API_TOKEN saved in the var and the middleware apparently doesn’t get that the session is expired.

So to obtain the API_TOKEN every time I’m doing an Ajax, request so when the session expires, I won’t get the token and therefore, I won’t be able to complete the request.

This is my setup.

web.php is where there is the only php route that points to a singlePageController:

Auth::routes();

Route::get(‘/{any}’, ‘SinglePageController@index’)->where(‘any’, ‘.*‘);

Then in the singlePageController I return the view:

class SinglePageController extends Controller
{
public function index() {
return view(‘app’, [‘loggedUser’ => auth()->user()]);
}
}

Then there is the api.php where there is the API routes. As you can see at the end there is the middleware to make it private. Just to make an example this is the one I use for updating the content:

Route::put(‘event/update/{slug}’, ‘EventController@update’)->middleware(‘auth:api’);

Then the related controller of that API route:

public function update(Request $request, $slug)
{
$event = Event::where(‘slug’, $slug)->first();

$event->title = $request->input(‘title’);

return new EventResource($event);
}

And in the end this is the Resource I use to define what and how the API data is going to be displayed:

public function toArray($request)
{
// return parent::toArray($request);

return [
‘id’ => $this->id,
‘title’ => $this->title,
‘slug’ => $this->slug,
‘curator’ => $this->curator,
‘featured_image’ => $this->featured_image,
‘body’ => $this->body,
‘date’ => $this->date
];
}

So this above is the flow I have. Then when I do an axios call to update the content, I’m doing something like:

axios({
method: ‘PUT’,
url: ‘/api/event/update/‘ + this.$route.params.slug + ‘?api_token=’ + this.isLogged.apiToken,
data: dataToSave,
headers: {
‘X-CSRF-TOKEN’: $(‘meta[name=”csrf-token”]‘).attr(‘content’)
}
})
.then((response) => {
this.getNotification(‘Success: The Event has been saved’);
})
.catch((error) => {
this.getNotification(‘Error: Impossible saving the event’);
console.log(error);
})

Do you know how to make it? or if there is a better way to accomplish that?

Solution :

you and do like, the login method should like this.

public function login(Request $request)
{

if (Auth::attempt([‘email’ => $request[‘email’], ‘password’ => $request[‘password’]])) {
$user = Auth::user();
$success = $user->createToken(config(‘app.name’))->accessToken;
return response()->json([“token” => $success, ‘status’ => 200]);
} else {
return response()->json([‘message’ => “Email or Password do not match”], 401);
}
}

[Vue.js] Using Angular6 application inside VueJs application Subscribe to RSS

We have Angular application (version 6.1.5), which makes HTTP request to the Restfull API.

We have used modular approach in Angular App. There is app level routing configurations and each modules have their own routing configuration.

This set up is perfectly fine and running without any hassles.

Now as per our new requirement, we need to use this Angular application withing VueJS application.

After our initial research, we used Angular Elements and created angular build. We used this build (containing JS and CSS file) withing the VueJS, we thought it worked fine, until we hit refresh on VueJS application.

Once we hit refresh, the Angular application routes are not working and we only see blank screen.

So what we would like to know is, whether our approach of using angular element is right one. Or are there any better approaches to use angular application within VueJS application.

Thanks for the help.

Solution :

Presumably none of the commenters on the original question are familiar with Web Components (of which Angular Element uses). Using multiple frameworks in combination with isolated web components is a perfectly normal and accepted practice. In fact, it is likely to become more popular.

Anyway, the actual problem here is a fundamental incompatibility of routing libraries. Because routing is so tied to the address bar and the HTML 5 History API, child components (regardless of any framework or web components) can’t simply work how you are expecting it to work. Firstly, vue.js Router is in the “parent” component while the Angular ones (via Web Components) try setup routing which then fails.

You will have to refactor the Angular components to not use routing.

This isn’t a vue.js vs Angular vs Web Component problem but a routing problem.

[Vue.js] Wrapping Vue computed properties and methods while preserving type signature on Vue.extend constructor Subscribe to RSS

to wrap all my defined methods and computed properties in a function that times their execution.

to preserve the IntelliSense predictions derived from the type signature of Vue.extend({…

I’ve failed to create my own method while maintaining the complex type signature without having to copy dozens of files from the vue.d.ts typings.

I’ve gotten moderate success from replacing Vue.extend before calling it, but I’d rather just have my own constructor method with the same typing benefits of the vue.js one.

Bulky but working example, which requires “noImplicitThis”: false in .tsconfig:

<template>
<div>
{ computedValue }
</div>
</template>

<script lang=”ts”>
import vue.js from ‘vue’;

const ext = Vue.extend;
Vue.extend = function (x: any, …rest:any[]) {
const f = x.computed.computedValue;
console.log(x, rest);
x.computed.computedValue = function () {
const start = Date.now();
const rtn = f.call(this, x, …rest);
console.log(`Took ${(Date.now() - start) / 1000} seconds`);
return rtn;
}
return ext.call(this, x, …rest);
} as any

const component = Vue.extend({
computed: {
computedValue() {
return ‘passed’;
}
}
});
Vue.extend = ext;
export default component;
</script>

Desired result: a method that is called instead of Vue.extend that will wrap the computed properties and methods in a chronometer while preserving IntelliSense on the component

Result so far: A bulky implementation that requires a lot of intervention in the implementation of each component in order to be used

Solution :

While typing up the example component for this, I managed to achieve what I wanted: A single method that wraps Vue.extend while hooking in a chronometer on certain component methods.

import vue.js from ‘vue’;
import { ThisTypedComponentOptionsWithArrayProps } from ‘vue/types/options’;
import { Extendedvue.js } from ‘vue/types/vue’;

export function wrap<Data, Methods, Computed, PropNames extends string = never>
(options: ThisTypedComponentOptionsWithArrayProps<Vue, Data, Methods, Computed, PropNames>):
ExtendedVue<Vue, Data, Methods, Computed, Record<PropNames, any>> {
if (‘computed’ in options) {
Object.keys(options.computed as any).forEach((key: string) => {
const f: Function = (options.computed as any)[key] as any as Function;
(options.computed as any)[key] = function (…args: any[]) {
const start = Date.now();
const rtn = f.apply(this, args);
console.log(`${key} took ${(Date.now() - start) / 1000} seconds.`);
return rtn;
};
});
}
if (‘methods’ in options) {
Object.keys(options.methods as any).forEach((key: string) => {
const f: Function = (options.methods as any)[key] as any as Function;
(options.methods as any)[key] = function (…args: any[]) {
const start = Date.now();
const rtn = f.apply(this, args);
console.log(`${key} took ${(Date.now() - start) / 1000} seconds.`);
return rtn;
};
});
}
return Vue.extend(options);
}

Simple call wrap({…componentOptions}) rather than Vue.extend({…componentOptions}) and it will hook the chronometer.

$options doesn’t play too nice, but being a little sneaky seems to suppress errors

export default wrap({
…{
a: 4
},
});

[Vue.js] Passing a Vue v-for value into a jinja/flask route Subscribe to RSS

I’m currently trying to implement vue.js into a current project where itwas using Jinja2 for the rendering, in all the images it makes a call to a Flask route to fetch the image from a directory outside of the project.

Old Flask/Jinja Code

What I need to do

<tr v-for=”doc in documents”>

<td>
<img src=”{ url_for(‘convert_to_image’, filepath=”doc.path”) }”>
</td>
</tr>

# ignore tr tags, this is going into a table.

Now this works, and is calling the Flask route but the vue.js variable isn’t converting to the value its staying as a string. I need to pass the variable into the flask route some how? SO after rendering what i’d end up with is

<img src=”/path/to/someImage.jpg”>

Solution :

I don’t know Flask at all so YYMV but if you can get it to generate the base part of the URL without knowing the filepath part, you can do something like this…

<img :src=”`{url_for(‘convert_to_image’, filepath=’’)}${doc.path}`“>

By the time vue.js gets this, it will see something like

<img :src=”`/path/to/${doc.path}`“>

as all server-side parts would have been rendered.

You may be able to omit that filepath=’’ value and you might need to insert a / between the server-side and client-side rendered parts but hopefully this points you in the right direction.

[Vue.js] Vue.js add the same class repeatedly to create a just updated effect Subscribe to RSS

Goal:

there is a list of items and when something changes on one of those items, to draw the user’s attention to it by making it have a yellow background that fades out to transparent.

How I’m attempting to do this:

My vue.js instance has a list of items.

Each item has a property, isChanged, which is a boolean value indicating whether that item has been changed by some action in the interface.

I’ve binded a class to the items so that when their isChanged property is true, the class highlight is added.

<ul v-for=’item in items’ :key=’item.id’>
<li :class=”{ ‘highlight’ : item.isChanged>{ item.name }</li>
</ul>

The highlight class simply changes the background to yellow then fades it to transparent:

.highlight {
animation: yellowfadingbox 4s;
}

@keyframes yellowfadingbox {
from {
background: @yellow;
}
to {
background: transparent;
}
}

So, as an example, there is a method updateItem that makes an ajax call and when it’s done, sets that items isChanged property to true.

updateItem: function (itemKey) {
axios.get(‘/item/update’, {
params: {
id: id,
}
}).then(response => {
this.item[itemKey].isChanged = true;
});
}

This works in that it adds the appropriate highlight class to the item, giving me the effect I want. However, moving forward, that highlight class always exists and so I can not recreate the effect.

How can I fix this approach/is there a smarter approach?

Solution :

Here’s one way you might do it.

I’m using a transition rather than an animation. Adding the highlight class sets the background to yellow. I then remove it again to get the transition back to transparent.

I’m using requestAnimationFrame to delay so that the transition has chance to take effect. There are two problems that the delay addresses. Firstly, we need to give vue.js chance to render. Secondly, we need to give the browser chance to apply the yellow background (style recalc), otherwise the transition won’t happen. There are various ways to achieve these two things. $nextTick could be used to overcome the first problem but we’d still need some way to kick the browser into applying the style. That gets fiddly as you’d need to grab a reference to the relevant element and then use getComputedStyle to force the style recalc on the background-color. requestAnimationFrame seemed a relatively painless solution by comparison.

In this example just click on the items to see the effect.

new Vue({
el: ‘#app’,
data: {
items: [{
name: ‘Red’,
id: 1,
isChanged: false
},
{
name: ‘Green’,
id: 2,
isChanged: false
},
{
name: ‘Blue’,
id: 3,
isChanged: false
},
{
name: ‘Yellow’,
id: 4,
isChanged: false
}
]
},
methods: {
onClick (item) {
item.isChanged = true;

requestAnimationFrame(() => {
item.isChanged = false;
});
}
}
});
.list-item {
transition: background-color 4s;
}

.list-item.highlight {
background-color: yellow;
transition: none;
}
<script src=”https://unpkg.com/vue@2.6.10/dist/vue.js"></script>
<div id=”app”>
<ul>
<li
v-for=”item in items”
:key=”item.id”
:class=”{ ‘highlight’ : item.isChanged}”
class=”list-item”
@click=”onClick(item)”
\>
{ item.name }
</li>
</ul>
</div>

[Vue.js] How to bind click events to elements with a specific class Subscribe to RSS

I’d like to bind click events on pageload to all elements that have the class “X”
I know that we can mount eventlisteners in the following way, but I can’t find out how to do the same for click events. somthing like: v-on:click=”onClick($event)”or @click.stop

This is what I use to for eventlisteners:

mounted:function(){
this.$el.addEventListener(‘click’, this.onClicked)
}

Solution :

I’ll do this the old fashioned way.

Using Jquery (or native JS)

$(document).on(‘click’, ‘yourCssClass’, function(e){
yourJsCode;
});

Solution 2:

You just have to pass the method on the v-on:click function defined on the HTML tag. See:

<button v-on:click=”sendMessage()” value=’Send’>Send Message</button>

methods: {
sendMessage(e) {
console.log(`Hello, world from the button ${e.target.value}`)
},
},

mounted: {
this.sendMessage()
}

Where e is the event dispatched when you click the button.