link822 link823 link824 link825 link826 link827 link828 link829 link830 link831 link832 link833 link834 link835 link836 link837 link838 link839 link840 link841 link842 link843 link844 link845 link846 link847 link848 link849 link850 link851 link852 link853 link854 link855 link856 link857 link858 link859 link860 link861 link862 link863 link864 link865 link866 link867 link868 link869 link870 link871 link872 link873 link874 link875 link876 link877 link878 link879 link880 link881 link882 link883 link884 link885 link886 link887 link888 link889 link890 link891 link892 link893 link894 link895 link896 link897 link898 link899 link900 link901 link902 link903 link904 link905 link906 link907 link908 link909 link910 link911 link912 link913 link914 link915 link916 link917 link918 link919 link920 link921 link922 link923 link924 link925 link926 link927 link928 link929 link930 link931 link932 link933 link934 link935 link936 link937 link938 link939 link940 link941 link942 link943 link944 link945 link946 link947 link948 link949 link950 link951 link952 link953 link954 link955 link956 link957 link958

[Vue.js] List directory contents with Apache

Let me start by saying that my knowledge of Apache is almost none, so I apologize if when not using the correct terminology.

there is a website written in Vue, and the routing is taken care by vue.js Router. In their documentation, they specify that in order for the router to work correctly, you have to put this in the .htaccess file of the website:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
</IfModule>

From what there is been able to understand, all requests are sent back to the index.html file which will take care of loading the correct component based on the path.

My goal is to now allow my website to have a path (let’s say /documents) which is not picked up by Vue, but instead shows the contents of the directory and allows you to both navigate and download the contents (Like this).

there is tried a few ways, but they all return a 403 or 500 (possibly due to a mistake in my config). I understand that I need to add a RewriteRule but all of those that I tried return weird errors.

Thanks in advance

Solution :

You can have multiple rewrite rules based on what the RewriteBase is . In the current set, the rule is applying to the root of the host.

You can add another rule with RewriteBase /documents/. More info: What does RewriteBase do and how to use it?

Solution 2:

I recommend reading the docs: https://httpd.apache.org/docs/2.4/mod/mod\_rewrite.html

The RewriteCond directive defines a rule condition.

So here a dirty explanation:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

So the RewriteConds says that if the given path/url isn’t a file (!-f) and not a directory (!-d) then the next rewrite rule (RewriteRule . /index.html [L]) takes action.

RewriteRule . /index.html [L]

“.” is a wildcard, so all urls will be redirect to index.html.
The [L] flags stops the execution (https://httpd.apache.org/docs/2.4/rewrite/flags.html#flag\_l)

The RewriteRule ^index\.html$ - [L] stops the execution if the url is index.html.

So, the rewrite rule fulfill the requirements and seems correct.

When you get a 403 you maybe need to add Options +Indexes to the config or htaccess.

Solution 3:

In the end, after looking through the docs, I was not able to understand how to set it up. I found this page, and using option #2 I was able to get the directory to at least show up.

I then added the auth to the folder through the .htaccess file and added the .htpasswd file with the username/password combo

TLDR

Create the folder in the location you want. In my case it was in httpdocs/documents
Create a .htaccess file where you put the following contents:

# Omit this section if you do not need the auth
AuthType Basic
AuthName “restricted area”
AuthUserFile /path/to/your/.htpasswd
require valid-user

Order allow,deny
Allow from all
Options +Indexes

Create the .htpasswd file in the location you specified above. To generate the username/password combo I used this

Any corrections are welcome!

[Vue.js] Is it good practice to use for loops to sort out data in the same function where it's fetched in Vue?

when using fetch to get some data from an API, I convert this to JSON and want to sort it into different categories. For example tickets (which is what I’m retrieving) with the status active should be in a different array than the ones with status waiting on customer. to use a for loop to sort through the results. Should I do this in the same function they’re fetched in?

Did a bit of googling but couldn’t find a post on this.

methods: {
fetchTickets() {
fetch(‘/api’)
.then(res => res.json())
.then(resJson => {
arrayLength = resJson.length
for(var i = 0; i < arrayLength; i++) {
if(resJson[i][‘status’] === ‘active’) {
//do something
}
else if(resJson[i][‘status’] === ‘waiting on customer’) {
// do something else
}
else {
// do a dance
}
}
});
},
}

So, is it okay to do the above or is it very sensitive to errors/is there a more convenient alternative?

Solution :

There is a more convient alternative.

You should create two API calls.

1.) /api/activeUsers
2.) /api/waitingCustomers

Then for each API call, you can use the .filter API and return the appropiate array

fetchActiveTickets() {
fetch(‘/api’)
.then(res => res.json())
.then(resJson => {
return resJson.filter(item => {
return item.status ===’active’
})
//do the same for waiting… i.e. resJson(item => {
//return item.status ===’waiting’
//})

}
});
},

Solution 2:

I would recommend using .filter() rather than looping over the array to split the source into the pieces you want.

data: {
activeTickets: [],
waitingTickets: []
}
methods: {
fetchTickets() {
fetch(‘/api’)
.then(res => res.json())
.then(resJson => {
this.activeTickets = resJson.filter(function(ticket) { return ticket.status === ‘active’ });
this.waitingTickets= resJson.filter(function(ticket) { return ticket.status === ‘waiting on customer’ });

// do things with the filters arrays…

});
},
}

Solution 3:

Try

methods: {
async fetchTickets() {
let res = await (await fetch(‘/api’)).json();
let active = res.filter(x=> x[‘status’]==’active’);
let waiting = res.filter(x=> x[‘status’]==’waiting on customer’);
// … do something
},
}

[Vue.js] How to make sure that the DOM elements I want to manipulate have loaded before trying to do anything with them in Vue.js?

I’ve been battling this problem since yesterday and I’m at my wits end. Currently, there is a method in vue.js file that does this:

methods: {
showSlides(n) {
let slides = document.getElementsByClassName(“mySlides”);

slides[0].style.display = “block”;
}
},
mounted(){
this.showSlides();
}

It finds all elements with the class of “mySlides”, stores them in a variable and then attempts to change the style of the first element. This function is called when the component is mounted().

Now, the problem is that I get an error which states “TypeError: Cannot read property ‘style’ of undefined”. Turns out that at the time of execution of this function, these DOM elements are undefined. I realized this by adding a @click=’showSlide()’ event to a button. When I click the button, the function runs successfully, however, when it is mounted() it doesn’t.

The code also works successfully in a plain HTML file where the script is at the bottom of the page. This is what leads me to believe that something fishy is going on.

Full Code:

<template>
<div class=”wrapper”>
<div class=”sight-container”>
<p class=’sight-name’>{ sight.name }</p>
<p>{ sight.formatted_address }</p>
<p>{ sight.formatted_phone_number }</p>
<p>{ sight.international_phone_number }</p>
<p>{ sight.website }</p>

<div class=”photos-container”>
<div v-for=’(image, index) in sightImages’ class=”mySlides”>
<div class=”numbertext”>{ index + 1 } / { sightImages.length }</div>
<img class=’sight-photos’ :src=”‘https://maps.googleapis.com/maps/api/place/photo?maxwidth=1920&photoreference=' + image.photo_reference + ‘&key=’”>
</div>

<a class=”prev” @click=’plusSlides(-1)’></a>
<a class=”next” @click=’plusSlides(1)’></a>

<div class=”caption-container”>
<p id=”caption”></p>
</div>

<div class=”row”>
<div v-for=’(image, index) in sightImages’ class=”column”>
<img class=”demo cursor” :src=”‘https://maps.googleapis.com/maps/api/place/photo?maxwidth=1920&photoreference=' + image.photo_reference + ‘&key=’” style=”width:100%” @click=”currentSlide(1)”>
</div>
</div>
</div>

</div>
</div>
</template>

<script>
import axios from ‘axios’

export default {
data(){
return {
placeId: this.$route.params.placeid,
sight: “”,
sightImages: [],
slideIndex: 1
}
},
methods: {
showSlides(n) {
let i;
let slides = document.getElementsByClassName(“mySlides”);
let dots = document.getElementsByClassName(“demo”);
let captionText = document.getElementById(“caption”);

if (n > slides.length) {
this.slideIndex = 1
}
if (n < 1) {
this.slideIndex = slides.length
}
for (i = 0; i < slides.length; i++) {
slides[i].style.display = “none”;
}
for (i = 0; i < dots.length; i++) {
dots[i].className = dots[i].className.replace(“ active”, “”);
}

slides[this.slideIndex-1].style.display = “block”;
dots[this.slideIndex-1].className += “ active”;
captionText.innerHTML = dots[this.slideIndex-1].alt;
},
plusSlides(n) {
this.showSlides(this.slideIndex += n);
},
currentSlide(n) {
this.showSlides(this.slideIndex = n);
}
},
mounted(){
axios.get(‘/getSight/‘ + this.placeId)
.then(response => {
this.sight = response.data.result.result
this.sightImages = response.data.result.result.photos
}).catch((error) => console.log(error));

this.showSlides(this.slideIndex);
}
}
</script>

Solution :

That’s because you’re using it wrong.

Normally, mounted are called after rendering component’s DOM, at this time component’s this.$el is ready to be used.

However, in mounted you’re calling asynchronous operation that updates data (and later DOM) upon completion, but you try to use its result before it happened.

It should be like this:

mounted() {
axios.get(‘/getSight/‘ + this.placeId)
.then(response => {
this.sight = response.data.result.result;
this.sightImages = response.data.result.result.photos;
this.$nextTick(() => {
this.showSlides(this.slideIndex);
});
}).catch((error) => console.log(error));
}

Small hint: rather than use el.className += … and el.className.replace(…) you can use el.classList.add(…) and el.classList.remove(…).

Docs: Element.classList

[Vue.js] Input field not reacting to data changes after being written to by a user

While creating a Vue.js application there is become stuck at a weird problem. to be able to manipulate an input field (think increment and decrement buttons and erasing a zero value on focus, so the user doesn’t have to) and up until a user writes to the input field, everything is fine. After that, however, further changes in the data are no longer represented in the input field.

As I was sure I could not be the only one with this particular problem, I searched extensively, but had no luck. What baffles me the most is that everything works until the field is written to, since I can not really imagine why this would remove the data binding.

The following code should show the same behavior. It is an input field component, which is initialized with a zero value. On focus the zero gets removed. This works, until a user manually writes to the field after which zero values will no longer be removed, even though the focus method fires, the if-condition is met and the data in the amount-variable is changed.

Vue.component(‘item’, {
data: function () {
return {
amount: 0
}
},
render: function (createElement) {
var self = this;

return createElement(‘input’, {
attrs: {
//bind data to field
value: self.amount,
type: ‘number’
},
on: {
//update data on input
input: function (event) {
self.amount = event.target.value;
},
//remove a zero value on focus for user convenience
focus: function (event) {
if (self.amount == 0 || self.amount == “0”) {
self.amount = ‘’;
}
}
}
})
}
})

Solution :

I think you need to use domProps instead of attrs to make it reactive. But I would suggest you use vue’s template syntax or if you insist on using the render function I would also suggest you to use JSX.

[Vue.js] How to fix the columns size in different screen resolutions using vuetify grid

I’m creating a simple dashboard using vue.js and Veutify. I choose to structure the layout using the grid system available in vuetify’s library. The problem is that I can’t get the same look depending on the screen resolution.
Is there any way to have the left container always with the width of the side drawer?

I already try to set the max-width of the side bar manually in 300px, but did’nt work.

<v-container grid-list-md text-xs-center>
<v-layout row wrap>
<v-flex xs3 class=”side”>
<SideBar/>
</v-flex>
<v-flex xs9 class=”main” >
<MainPage/>
</v-flex>
</v-layout>
</v-container>

I expect

I got

edit: HTML/CSS generated: https://pastebin.com/bLYgv5pz

Solution :

The short answer is that the 3-column area is designed to always be 25% of the container width for grids like this. If you want to keep the sidebar the size of the 3-column section, you can give it max-width:100%;

I’m not familiar with the exact styling used by Vuetify, but if you can post the generated HTML and CSS, it should certainly be possible to suggest how you might restrict the growth of that column.

[Vue.js] VueJS Set variable name using string

Is it possible to set a variable myvar using a string in the example below ?

<script>
export default {
data() {
return {
myvar: ‘foo’
};
}
}
</script>

I tried this which didn’t work:

eval(‘myvar’): ‘foo’

Solution :

Here is a very crude and basic example of how you would accomplish something like this:

new Vue({
el: “#app”,
data() {
return {
myVar: ‘hello’
}
},
methods: {
changeVal(varName, newValue) {
this[varName] = newValue;
}
}
});
<script src=”https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id=”app”>
{myVar}
<button @click=”changeVal(‘myVar’, ‘world’)”>change myVar</button>
</div>

Here, we are utilizing a method that takes the name of the variable and the value to change it to - then passing it to the current vue.js model instance (represented by this inside of methods) to modify the value of the dynamic variable name.

Solution 2:

To change data, you just need to modify it like you would any other mutable variable. It depends how the component is set up. Looking at the docs (https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties), one way of doing it is like this (modified example from the above link):

const vue.js = new Vue({
el: ‘#app’,
data: {
myvar: ‘foo’
},
template: ‘<div>{ myvar }</div>’
})

vue.myvar = ‘bar’
<script src=”https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id=”app”></div>

If you want to do it from a method (e.g. calling a method from within a template), refer to it with the this keyword:

const vue.js = new Vue({
el: ‘#app’,
data: {
myvar: ‘foo’
},
template: ‘<div><div>{ myvar }</div><button @click=”changeMe”>Click Me</button></div>’,
methods: {
changeMe() {
this.myvar = ‘bar’
}
}
})
<script src=”https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id=”app”></div>

[Vue.js] vuetify card without left and right margin

when new to vue.js and vuetify and just use v-card tag from vuetify.

that the v-card have 100% width, (without left or rigth side spacing)

Is there any configuration that can be made on these initial tags ?

<v-layout
column
justify-center
align-center
\>

<v-flex
xs2
sm2
md2
\>

How can it ben done ?

I try :

.section{
padding-top: 100px;
padding-bottom: 100px;
width:100%;
}

and :

<div class=”section section_dark”>services</div>

But still there is some left and right space for this div.

Solution :

You can try row instead of column :

<v-layout
row
justify-center
align-center
\>

and use special props for card :

<v-card
min-width=”100%”
\>

[Vue.js] Jump to position on click (access class from other Vue component)

Explanation of problem

If a user clicks on the login link the view shall jump down to the login window where a user can type in userdata.

when aware how to do this within a single file using document.getElementById(‘login-window’).scrollIntoView()

However, there is a project with various single Vue.js component files. The login-link is within one “label” component. But the actual login-window is located in another component called “loginWindow”, thus also the id / class “login-window” is stored in “loginWindow”.

I tried to grab the “login-window” element with getElementById within my “label” component, but I believe it cannot access it since it is in another component.

This is the template code from “loginWindow”

<template>
<LoginGrid class=”login-window” :as-grid=”true” :class=”classes” autocomplete=”off”>
<OCard class=”login-card” :border=”false”>
<div class=”login-headline f-copy f-bold l-color-primary”>{ t(‘headline’) }</div>
<!– online state –>
<template v-if=”isLogged”>
<OButton color=”secondary” @click=”onClickLogout”>{ t(‘logout-label’) }</OButton>
</template>
<!– offline state –>
<template v-else>
<div class=”login-inputs”>
<LoginInput
class=”login-input-card-number” />

</div>


<OLink
type=”secondary”
class=”login-mode-link f-regular f-copy-small”
:no-router=”true”
@click=”onSwitchMode”
\>
{ modeLabel }
</OLink>

</template>
</OCard>
</LoginGrid>
</template>

Here is what I’ve tried exactly

Within my “label” component there is implemented this method with an else-statement:

export default {
name: ‘loginWindow’,

methods: {
onClick() {
if (this.isLogged) {

} else {
if (isBrowser) {
document.getElementById(“login-window”).scrollIntoView();
}
}
},
},
}

So if the user is not logged-in, then onClick() it should scroll to the id of “login-window”.

However, this solution does not work. I get an error saying “Cannot read property ‘scrollIntoView’ of null”.

Any ideas how to do this with JavaScript within a Vue.js component?

Solution :

login-window is Class not ID in the HTML. Try this:

document.querySelector(“.login-window”).scrollIntoView();

[Vue.js] Adsense injecting style tag into my page (in chrome)

when working on a website that is heavily front-end (vue) and thus when using the async version of adsense.

When testing in various browsers I noticed a display issue in chrome where the height of my page was being changed immediately after ads loaded. Hours later I discovered that within show_ads_impl.js it is injecting style=”height: auto !important;” (or similar) into various places in my source code.

I could not find help on this anywhere and am desperate to find a solution - this really impacts the user experience within my project quite negatively.

I asked for help on the adsense support website and did not get a single response.

I was successful at removing the style attribute added by the ads with a delayed callback routine in my javascript - but as you can imagine that caused the page to flicker in a way that is certainly unpleasant.

https://pagead2.googlesyndication.com/pagead/js/r20190408/r20190131/show\_ads\_impl.js

Note the link above will not contain the “injection” code unless you download it from chrome.

The code in question in the file above looks like this:

a.o && !c && f && (e.setProperty(“height”, “auto”, “important”),
d && !$v(String(d.minHeight)) && e.setProperty(“min-height”, “0px”, “important”),
d && !aw(String(d.maxHeight)) && e.setProperty(“max-height”, “none”, “important”))) : (Yv(a, 1, l, c, “height”, h, a.B, a.l),

Solution :

For anyone that may stumble on this in the future. Below is how I was able to “solve” the problem in a way that I deemed good enough to move on.

Like I stated above, google Adsense was injecting style=”height: auto !important; min-height: 0px !important;” into my primary page wrapper element on my website.

Below is the code I used to solve the problem - essentially undoing what Adsense does.

// this code listens for a mutation on the main-wrapper element and resets
// the style attribute back to “null”.
// This is necessary because Google Adsense injects style into this main-wrapper
// element changing its height properties. Note: This only occurs in Chrome.
let wrapper = document.getElementById(‘main-wrapper’)
const observer = new MutationObserver(function (mutations, observer) {
wrapper.style.height = ‘’
wrapper.style.minHeight = ‘’
})
observer.observe(wrapper, {
attributes: true,
attributeFilter: [‘style’]
})

[Vue.js] CKFinder issue Uncaught TypeError Cannot read property 'modal' of undefined with CKEditor 5 - Vue js

I’m trying to integrate CKFinder in vue.js js application. But facing this issue Uncaught TypeError: Cannot read property ‘modal’ of undefined.

I’m following the official documentation for CKEditor5 / CKFinder for vue.js js.

Here the ckfinder configuration.

ckfinder: {
// Define the CKFinder configuration (if necessary).
options: {
resourceType: ‘Images’
},
}

Here’s the complete error message shown in the browser console.

Uncaught TypeError: Cannot read property ‘modal’ of undefined
at CKFinderCommand.execute (ckfindercommand.js?9ed3:153)
at CKFinderCommand.eval (observablemixin.js?3466:268)
at CKFinderCommand.fire (emittermixin.js?e4c7:236)
at CKFinderCommand.(:9191/anonymous function) [as execute] (webpack-internal:///./node_modules/@ckeditor/ckeditor5-utils/src/observablemixin.js:296:19)
at CommandCollection.execute (commandcollection.js?e961:92)
at ClassicEditor.execute (editor.js?7e01:299)
at ButtonView.eval (ckfinderui.js?8a75:47)
at ButtonView.fire (emittermixin.js?e4c7:236)
at TemplateToBinding.eval (buttonview.js?d175:167)
at ProxyEmitter.callback (template.js?56c1:1208)

Solution :

You need to attach CKFinder to the page first, so CKEditor 5 can use it.

The easiest way to do so is by using a script tag:

<script src=”https://example.com/ckfinder/ckfinder.js"></script>

More information: https://ckeditor.com/docs/ckeditor5/latest/features/image-upload/ckfinder.html#configuring-the-full-integration