Vuejs

Subscribe to Vuejs feed
most recent 30 from stackoverflow.com 2017-09-14T21:10:11Z
Updated: 7 years 1 week ago

Moving Vue components around inside the dom?

Tue, 2017-07-18 14:34

I am moving Vue components up in the dom if I am on mobile since I want to use positioning absolute and want to make sure I am not within a relative container.

if (this.mobile) { this.$el.parentNode.removeChild(this.$el); document.getElementById('vue').appendChild(this.$el); } else { // Place the element back at it's original location. }

This code is placed with a debounced resize method so it also works on resizing of the window.

It works fine but when I start out on mobile and resize back to desktop I need to get the original dom location of where the component was first initialized.

This might be a Javascript only question but how can I get the original location of the exact dom position of this component so I can place it back again?

Edit

I am saving the initial parent element with:

this.parent = this.$el.parentElement;

This does not guarantee the right order in the parent element though when I append the element back to the parentElement again.

Categories: Software

vue.js firing $emit not received by $on

Tue, 2017-07-18 13:53

Vue.component('rating-edit', { template:` <form> <input v-model="rating.title" type="text"> <textarea v-model="rating.remark">{{rating.remark}}</textarea> <button type="button" @click="submit"> Save </button> </form>`, props:['rating'], methods: { submit: function submit () { let rating = this.rating; this.$emit('submit', rating); console.log('submit was emitted'); } } }); const aRating = { title: 'title', remark: 'remark' }; let vueApp = new Vue({ el: '#rating-edit-container', data: { rating: aRating } }); vueApp.$on('submit', function(rating) { console.log('vue on submit', rating); }); <script src="https://vuejs.org/js/vue.min.js"></script> <div id="rating-edit-container"> <rating-edit :rating="rating"></rating-edit> </div>

In a legacy frontend code I'd like implement a vue based componentized form and have it return the data on submit.

This is the component code. Please note the submit function firing this.$emit('submit', rating);

let result = { props:['rating'], methods: { submit: function submit () { let rating = this.rating; this.$emit('submit', rating); console.log('submit fired'); } } }; export default result;

And now in the legacy code, I am waiting for the events:

import Vue from 'vue'; import ratingEditVue from './rating-edit.vue'; Vue.component('rating-edit', ratingEditVue); const aRating = { title: 'title', remark: 'remark' }; let vueApp = new Vue({ el: '#rating-edit-container', data: { rating: aRating } }); vueApp.$on('submit', function(rating) { console.log('vue on submit', rating); });

As far as I understand the Vue events this should work. But $on('submit', handlerFunction) just never gets called.

Addendum:

I've fiddled the example. I apologize for not having done this in the first place.

Categories: Software

Vue.js - Push to array with v-model

Tue, 2017-07-18 13:18

I'm new to Vue.js, and I'm triing to create a shop app with vue & webpack. I have some products in a json file, and rendering them with a v-for.

When clicking on "Add to cart" button, it should put the product number, and the selected quantity to an array.

How can I properly increase quantity for a specific product? So far I have the following:

<template> <div v-for="(product, index) in products" > <div><img :src="product.product_image" /></div> <div> <input type="number" min="0" v-model="qty[index]" /> <button @click="addToCart(product.id, qty[index])">Add to cart</button> </div> </div> </template> <script> import productList from '../products.json'; export default{ name: 'shop', data(){ return { products: productList, cartElements: [], qty: [], } }, props: [ 'itemsInCart' ], methods:{ addToCart(product_id, quantity){ this.cartElements.push( { "id" : product_id, "quantity" : quantity, } ); console.log(this.cartElements); }, }, } </script>

The result is ok, but the input fields are acting weird.

E.g.: If I increase the third product's input, it sets the first and second product input to 1, and only then sets the third input to the desired number.

Categories: Software

How to use Graphql in NuxtJs

Tue, 2017-07-18 13:14

So I want to implement GraphQL into NuxtJs.

Now I need to have a provider into the root element, but NuxtJs doesn't give me this option.

How would I inject the apolloProvider into the root Vue element?

What I'm trying to accomplish:

https://github.com/Akryum/vue-apollo

const apolloProvider = new VueApollo({ defaultClient: apolloClient, }) new Vue({ el: '#app', apolloProvider, render: h => h(App), })

What I've tried:

Creating a plugin: /plugins/graphql.js:

import Vue from 'vue' import { ApolloClient, createBatchingNetworkInterface } from 'apollo-client' import VueApollo from 'vue-apollo' // Create the apollo client const apolloClient = new ApolloClient({ networkInterface: createBatchingNetworkInterface({ uri: 'http://localhost:3000/graphql' }), connectToDevTools: true }) // Install the vue plugin Vue.use(VueApollo) const apolloProvider = new VueApollo({ defaultClient: apolloClient }) export default apolloProvider

Importing the apolloProvider in .nuxt/index.js:

... import apolloProvider from '../plugins/graphql' ... let app = { router, store, apolloProvider, _nuxt: { defaultTransition: defaultTransition, transitions: [ defaultTransition ], ...

Unfortunately this provides me with 2 problems; each time the server restarts, my code in the .nuxt directory is wiped. Besides that it gives me the following error:

TypeError: Cannot set property '__APOLLO_CLIENT__' of undefined at new ApolloClient (/current/project-nuxt/node_modules/apollo-client/src/ApolloClient.js:112:37) at Object.<anonymous> (plugins/graphql.js:6:21) at __webpack_require__ (webpack:/webpack/bootstrap 8a1e0085b0ebc1e03bd0:25:0) at Object.module.exports.__webpack_exports__.a (server-bundle.js:1060:76) at __webpack_require__ (webpack:/webpack/bootstrap 8a1e0085b0ebc1e03bd0:25:0) at Object.<anonymous> (server-bundle.js:1401:65) at __webpack_require__ (webpack:/webpack/bootstrap 8a1e0085b0ebc1e03bd0:25:0) at server-bundle.js:95:18 at Object.<anonymous> (server-bundle.js:98:10) at evaluateModule (/current/project-nuxt/node_modules/vue-server-renderer/build.js:5820:21) at /current/project-nuxt/node_modules/vue-server-renderer/build.js:5878:18 at /current/project-nuxt/node_modules/vue-server-renderer/build.js:5870:14 at Nuxt.renderToString (/current/project-nuxt/node_modules/vue-server-renderer/build.js:6022:9) at P (/current/ducklease-nuxt/node_modules/pify/index.js:49:6) at Nuxt.<anonymous> (/current/project-nuxt/node_modules/pify/index.js:11:9) at Nuxt.ret [as renderToString] (/current/project-nuxt/node_modules/pify/index.js:72:32) at Nuxt._callee2$ (/current/project-nuxt/node_modules/nuxt/dist/webpack:/lib/render.js:120:24) at tryCatch (/current/project-nuxt/node_modules/regenerator-runtime/runtime.js:65:40) at GeneratorFunctionPrototype.invoke [as _invoke] (/current/project-nuxt/node_modules/regenerator-runtime/runtime.js:303:22) at GeneratorFunctionPrototype.prototype.(anonymous function) [as next] (/current/project-nuxt/node_modules/regenerator-runtime/runtime.js:117:21) at step (/current/project-nuxt/node_modules/babel-runtime/helpers/asyncToGenerator.js:17:30) at /current/project-nuxt/node_modules/babel-runtime/helpers/asyncToGenerator.js:28:13
Categories: Software

Vue filters migration from vue 1 to vue 2

Tue, 2017-07-18 13:09

I have problem with migratiing filters from vue 1 to vue 2, I created exactly what I need here (highlighting text which match the input text):

Vue.component('demo-grid', { template: '#grid-template', props: { filterKey: String }, data: function () { return { searchParams: [ { key: '' } ], suggestions: [ { message: 'Foo' }, { message: 'Bar' }, { message: 'Foobar' }, { message: 'pikachu' }, { message: 'raichu' } ] } }, filters: { highlight: function(words, query){ var iQuery = new RegExp(query, "ig"); return words.replace(iQuery, function(matchedTxt,a,b){ return ('<span class=\'highlight\'>' + matchedTxt + '</span>'); }); } } }) // bootstrap the demo var demo = new Vue({ el: '#demo' })

https://jsfiddle.net/t5ac1quc/23/ VUE-1 resource
https://jsfiddle.net/t5ac1quc/25/ VUE-2 resource

I would be very grateful, for all the answers

Categories: Software

Vuejs: component aggregation

Tue, 2017-07-18 13:06

Starting from the following simple reddit-like example : https://jsfiddle.net/coligo/g7mu5ndz/

Vue.component('post', { template: "#post-template", props: ['post'], data: function () { return { upvoted: false, downvoted: false }; }, methods: { upvote: function () { this.upvoted = !this.upvoted; this.downvoted = false; }, downvote: function () { this.downvoted = !this.downvoted; this.upvoted = false; } }, computed: { votes: function () { if (this.upvoted) { return this.post.votes + 1; } else if (this.downvoted) { return this.post.votes - 1; } else { return this.post.votes; } } } }); var vm = new Vue({ el: "#app", data: { posts: [{ title: "A post for our reddit demo starting at 15 votes", votes: 15 }, { title: "Try out the upvoting, it works, I promise", votes: 53 }, { title: "coligo is the bomb!", votes: 10 }] } });

I'd like to :

  • a) Display the total number of upvotes (under the list of posts, in the #app div
  • b) For each post, display the percentage of total upvotes it has gained

Is this possible without managing each post state in the parent?

Categories: Software

Vuejs on IOS wont detect changes when using es6 Proxy instance

Tue, 2017-07-18 12:54

Here is my sample code using vuejs 2 framework:

a= {_data:{x: 2}} b = new Proxy(a, { get(target, name){ if(name !== '_data') return target._data[name] return target._data; }, set(target, name, value){ if(name !== '_data') target._data[name] = value else target[name] = value; return true; } }) v = new Vue({ el: '#app', data:{ c: b } });

It works properly on Chrome an Firefox both in android and desktop version, But when I run it on IOS, vue won't detect changes of data. Is this because of IOS support of ES6 Proxy??

Here is a jsfiddle link of above sample code: https://jsfiddle.net/aminfa92/j1oxcuLq/

Categories: Software

How can I use Blade in Vue files?

Tue, 2017-07-18 12:04

I'm trying to use Blade in my Vue file carousel-signUp.vue

Like:

<template> <div> <form action="{{route('dump')}}" method="POST" > /* Some code here...*/ </form> </div> </template>

But in the end I'm getting an error.

The compiler can't understand the difference between Vue syntax and Blade syntax. How can I define Blade syntax in Vue files?

Or, does anyone have an idea how to use {{route('dump')}} value in my vue file?

Categories: Software

for loop through array and bind class to element class attribute in vuejs

Tue, 2017-07-18 11:55

I am trying to bind classnames into the class attribute with vuejs looping through an array like this:

Here I pass the method call in a :class="paymentTypeClass(value)" to bind to the vue template like so:

<li v-for="card in paymentType" class="o-pf-list__item" :class="paymentTypeClass(value)"> {{ card }} </li> new Vue ({ el: '#app', data: { paymentType: ['paymentType1', 'paymentType2', 'paymentType3', 'paymentType4', 'paymentType5'] }, methods: { functionName: function(value) { var i = 0; for (i in this.paymentType) { value = 'o-pf-list__item--' + this.paymentType[i]; } return value + ' pull-left'; } } });

The result is that it only prints out the last index value in the array so it is actually overwriting. Why is this? Please help.

Logs in the console:

o-pf-list__item--bitcoin app.js:51663 o-pf-list__item--credit app.js:51663 o-pf-list__item--debitcard app.js:51663 o-pf-list__item--eft app.js:51663 o-pf-list__item--masterpass app.js:51663 o-pf-list__item--bitcoin app.js:51663 o-pf-list__item--credit app.js:51663 o-pf-list__item--debitcard app.js:51663 o-pf-list__item--eft app.js:51663 o-pf-list__item--masterpass app.js:51663 o-pf-list__item--bitcoin app.js:51663 o-pf-list__item--credit app.js:51663 o-pf-list__item--debitcard app.js:51663 o-pf-list__item--eft app.js:51663 o-pf-list__item--masterpass app.js:51663 o-pf-list__item--bitcoin app.js:51663 o-pf-list__item--credit app.js:51663 o-pf-list__item--debitcard app.js:51663 o-pf-list__item--eft app.js:51663 o-pf-list__item--masterpass app.js:51663 o-pf-list__item--bitcoin app.js:51663 o-pf-list__item--credit app.js:51663 o-pf-list__item--debitcard app.js:51663 o-pf-list__item--eft app.js:51663 o-pf-list__item--masterpass
Categories: Software

Rails System Test Not Loading Vue

Tue, 2017-07-18 11:06

I have a Vue feature in my rails 5.1 app that basically accepts a deeply nested form. The feature works perfectly in development, staging and production, however, when using the new minitest system tests with selenium and capybara, vue doesn't appear to load. As Selenium shows you whats happening in real time, I can see that the rails elements (such as _header, _footer, h1-Title) are all loading fine, but the Vue piece never appears.

Here is my testing setup:

Gemfile

group :test do gem 'minitest-rails' gem 'minitest-reporters' gem 'minitest-rails-capybara' gem 'faker' gem 'capybara', '~> 2.7', '>= 2.7.1' gem 'selenium-webdriver' gem 'simplecov', :require => false end

test/test_helper.rb

ENV["RAILS_ENV"] = "test" require 'simplecov' SimpleCov.start 'rails' require File.expand_path("../../config/environment", __FILE__) require "rails/test_help" require "minitest/rails" require "minitest/rails/capybara" require "minitest/pride" require 'minitest/reporters' require "support/test_password_helper" Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new ActiveRecord::FixtureSet.context_class.send :include, TestPasswordHelper class ActiveSupport::TestCase require "#{Rails.root}/db/seeds.rb" fixtures :all require 'minitest/autorun' include TestPasswordHelper # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order. # Add more helper methods to be used by all tests here... def sign_in(user) post user_session_path \ 'user[email]' => user.email, 'user[password]' => user.password end def submit_form find('input[name="commit"]').click end end

test/application_system_test_case.rb

require "test_helper" class ApplicationSystemTestCase < ActionDispatch::SystemTestCase driven_by :selenium, using: :chrome, screen_size: [1400, 1400] include Devise::Test::IntegrationHelpers end

test/system/proposals_test.rb

require "application_system_test_case" class ProposalsTest < ApplicationSystemTestCase test 'create a proposal' do sign_in users(:martin) @supplier = businesses(:supplier_two) @project = projects(:pete_project_three) visit dashboard_path assert_selector 'h3', text: @supplier.display_name assert_link text: 'Propose for project' click_on 'Create Proposal' assert_selector 'h1', text: 'New Proposal' assert_selector 'small', text: '(Version: 1)' fill_in 'title0', with: 'This is a title' fill_in 'body0', with: 'This is a body' click_on 'Add Section' fill_in 'title1', with: 'This is a second title' fill_in 'body1', with: 'This is a second body' end end

The test itself is failing at fill_in 'title0', with: 'This is a title' because the vue feature doesn't load

Note I am using turbolinks, but as mentioned, it's all working perfecting in practice, its just not loading for the system tests.

Happy to provide more detail if needed

Categories: Software

(vue-loader) How to change file name in source map?

Tue, 2017-07-18 10:42

chrome devtool

In source map path of .vue file is missing

How can I add path of file in sourcemap?

Categories: Software

Loading single file components in MVC5 using webpack

Tue, 2017-07-18 10:41

I have a MVC solution in VS2015 in wich I use vue.js to bind data, I tried to use webpack to use single file components with extension .vue.

On first instance I tried to generate 1 file.js foreach file.vue with this config:

const fs = require("fs"); const path = require("path"); // build an object that looks like // { // "filename": "./filename.vue" // } // to list the entry points for webpack to compile. function buildEntry() { const reducer = (entry, file) => { entry[file.split(".").shift()] = `./Vue/${file}`; return entry; }; return fs.readdirSync(path.join(__dirname, "Vue")) .filter(file => file.endsWith(".vue")) .reduce(reducer, {}); } module.exports = { entry: buildEntry(), output: { path: path.join(__dirname, "Vue"), filename: "[name].js", library: "[name]" }, module: { loaders: [ { test: /\.vue$/, loader: 'vue-loader' }, ], } }

So I could use a new component like this:

Vue.component("foo", foo);

But that generates to much .js files and it's dificult to maintain so I tried to unify them with this config:

module.exports = { entry: "./Vue/BundleIndex.js", output: { path: __dirname, filename: "./Vue/bundle.js", }, module: { loaders: [ { test: /\.vue$/, loader: 'vue-loader' }, ], } }

with this bundleIndex.js :

import foo from '.\\foo.vue' import example from '.\\example.vue'

I tried to use components as I used to, but I can't. what I'm missing here?

Categories: Software

Accessing _this

Tue, 2017-07-18 10:05

I have a typescript file... and it's failing TSLint. Was hoping someone could answer this.

So the object looks something like this:

export default class Container extends Vue { // methods doSomething() { console.log('something happened') } items: object[] = [ { title: test, onclick: _this.doSomething(); } ] }

I tried using this instead of _this, but this only refers to the individual object in items. So then I found in Chrome dev tools that I can use _this to access the containing class. However, when I put this code thru TSLint, it complains that it cannot find the name '_this'.

My project uses tslint-config-airbnb.

Thanks. John.

Categories: Software

What decides the directives bind sequences in Vue.js 1.0?

Tue, 2017-07-18 09:21

What's the custom directives bind sequences in Vue.js 1.0? Why the console.log result is :

bind loading

bind load

bind calendar

bind filterpanel

bind footprint

Code example is here:

// HTML <!-- Directives--> <div v-mask="UI.showMask"></div> <div v-loading="UI.showLoading"></div> <div v-load = "request.isLoadData"></div> <div v-calendar = "pageParams.leaveDate"></div> <div v-footprint = "UI.footprint"></div> // js Vue.directive('calendar', { bind: function () { console.log('bind calendar') // ... } }); Vue.directive('mask', { bind: function () { console.log('bind mask') // ... } }); Vue.directive('loading', { bind: function () { console.log('bind loading') // ... } }); Vue.directive('load', { bind: function () { console.log('bind load') // ... } update: function () { // send Query ... } }); Vue.directive('footprint', { bind: function () { console.log('bind footprint') // ... } });
Categories: Software

Vue.js nextTick inside computed property

Tue, 2017-07-18 08:51

I have "context menu" component. Computed properties top and left define menu position using $event property. But when I trying to open context menu, menu element is not rendered yet and top cannot be calculated without menu's offsetHeight, so I figured out to use some "nextTick hack" inside computed property:

top() { if (!this.menuIsRendered) { // by default, menuIsRendered is false this.$nextTick(() => { this.menuIsRendered = true }) return 0 } ... // menu element is rendered, calculate top value },

Is this ok? I think there must be a better way to do this.

Also, full component code:

<template> <div ref="menu" :style="{top: `${top}px`, left: `${left}px`}" v-click-outside="close" @contextmenu.prevent v-if="show"> <slot></slot> </div> </template> <script> export default { props: [ 'show', 'event' ], data() { return { menuIsRendered: null, } }, computed: { top() { if (!this.menuIsRendered) { this.$nextTick(() => { this.menuIsRendered = true }) return 0 } let top = this.event.y let largestHeight = window.innerHeight - this.$refs.menu.offsetHeight - 25 return top > largestHeight ? largestHeight : top + 1 }, left() { if (!this.menuIsRendered) { return 0 } let left = this.event.x let largestWidth = window.innerWidth - this.$refs.menu.offsetWidth - 25 return left > largestWidth ? largestWidth : left + 1 }, }, methods: { close() { this.$emit('close') }, } } </script>

Component usage:

<context-menu @close="close" :event="event" :show="show"> <div @click="doAction">Action</div> <div @click="doAnotherAction">Another action</div> </context-menu>
Categories: Software

In Framework7 Vue, is it possible to create a sortable list that is activated by tap and hold?

Tue, 2017-07-18 08:13

Tapping and holding to reorder list items is a common interface pattern in apps now.

Is there anyway to create a sortable list in this way in Framework7 Vue?

I'm currently using SortableJS / Vue Draggable to accomplish this, but the animation is not quite as slick as the sortable that is built into Framework7.

Please see this video of my current implementation to understand what I mean

Categories: Software

Vue.js methods vs computed properties. How they interact with the DOM

Tue, 2017-07-18 06:35

I am trying to figure out when to call the methods property, versus when is best to call a computed property. It seems to me that computed is generally preferable since a method will respond anytime a property is called which accesses the DOM.

In the following code, the two buttons tracks a basic counter which increments by 1. The same output is passed to the DOM through a method and through a computed property. Every increment triggers both the computed and the methods properties as shown in the console.

<div id="content"> <!--counter control--> <button v-on:click="counter++">Increase Counter</button> <button v-on:click="counter--">Decrease Counter</button> <!--counter output--> <p>{{counter}}</p> <p>{{ resultMethod() }}</p> <p>{{ resultComputed }}</p> </div> <script> new Vue({ el: '#content', data: { counter: 0 }, computed: { resultComputed: function(){ console.log("computed.result was run"); return this.counter < 5 ? 'small_number' : 'LARGENUMBER'; } }, methods: { resultMethod: function(){ console.log("methods.result was run"); return this.counter < 5 ? 'small_number' : 'LARGENUMBER'; } } }) </script>

Now if we add another couple data properties we can see that tracking them doesn't cause the method or the computed property to be triggered.

<!--new data options--> <button v-on:click="secondCounter++">Second Counter</button> <button v-on:click="formSubmit=true">Form Submit</button> //New Data Properties secondCounter: 0, formSubmit: false

Now displaying these data properties to the DOM shows first that the data is indeed being tracked correctly, and second these actions trigger the same methods property as our counter even though these variables are not related to this method.

<p>{{secondCounter}}</p> <p>{{formSubmit}}</p>

Finally, if we create an entirely random and unrelated method and reference it in the DOM, this too will be called everytime any of our variables are changed from the DOM. I use the simple method as an example.

<h2>{{ unrelatedMethod() }}</h2> unrelatedMethod: function(){ console.log("We are now using another random method"); var number = 2000; return number; }

So what exactly is happening here behind the scenes? Does Vue have to run every related property everytime the DOM is updataed? When would methods be a better choice over computed properties?

Categories: Software

vue js passing "top-level" Boolean not working, only nested

Tue, 2017-07-18 06:29

This is weird. When I define the Boolean property showModal at the top level it is simply being ignored by vue.js. Here's what I am doing:

//Component: export default { props:['rating', 'showModal'], data: function data () { return { rating: this.rating, showModal: this.showModal }; } };

Invoking the view:

const sharedRating = { title: '', remark: '' }; let showModal = false; new Vue({ el: '#rating-edit-container', data: { showModal: showModal, rating: sharedRating } }); showModal = true;

Then both values are being passed to the component:

<rating-edit :rating="rating" :show-modal="showModal"></rating-edit>

But when I change the value of showModal nothing happens.

If I pass showModal inside the rating object and use that nested property everything works fine:

const sharedRating = { showModal: false, title: '', remark: '' }; new Vue({ el: '#rating-edit-container', data: { rating: sharedRating } }); sharedRating.showModal = true;

Shouldn't "stand alone" boolean properties also be working in Vue or do they always need to be "wrapped"?

Categories: Software

Vue Router with Render Template

Tue, 2017-07-18 05:27

I'm a beginner used vue js. I tried vue router to navigation in my page. Everything went smoothly and easily. But I have a problem, when navigation need template to show page corresponding. Actually, I want my script neatly organized by splitting the file. Such as rooting itself , .html itself, etc. This is my script :

Route.js

/* Configuration Routing */ //const Home = { template: 'templates/home.html' }; const Thread = { template: '<div>THREAD</div>' }; const Tag = { template: '<div>TAG</div>' }; const TrendingTag = { template: '<div>TRENDING TAG</div>' }; const Category = { template: '<div>CATEGORY</div>' }; const User = { template: '<div>USER</div>' }; const Home = Vue.component('home', function(resolve) { $.get('templates/home.html').done(function(template) { resolve({ template: template, data: function () { return { message: 'Welcome' }; } }); }); }); //const Home = Vue.component('home', require('assets/js/controllers/home.js')); const routes = [ { path: '/', component: Home }, { path: '/thread', component: Thread }, { path: '/tag', component: Tag }, { path: '/trending-tag', component: TrendingTag }, { path: '/category', component: Category }, { path: '/user', component: User } ]; const router = new VueRouter({ mode: 'history', routes }); const app = new Vue({ router }).$mount('#app');

In this case, actually const home must exist in another file. Like home.js. Because I have to create data in home.js.

Home.js

Vue.component('homepage', function(resolve) { $.get('templates/home.html').done(function(template) { resolve({ template: template, data: function () { return { message: 'Welcome' }; } }); }); });

home.html

<div id="homepage"> <template id="home"> <h3 class="page-title" id="content"> {{ message }} </h3> </template> </div>

Can you help me please ? I really stuck with this case. Thank you.

Categories: Software

Force refresh of an affix in Vue

Mon, 2017-07-17 23:35

I am using a bootstrap affix within a Vue JS page. When I first navigate to the route containing the affix (the affix visibility is controlled via v-if), it works perfectly with scrolling. However, when I navigate away from that route and then back again, the affix is broken: it is stuck at the top of the page and doesn't scroll.

I have found online that, were I using jquery, I could call $('#affix').affix('checkPosition') to force the affix to reposition (but I don't have access to jquery).

I suspect the issue is that Vue is creating the affix on the first load, and then caches the same DOM object to be used later. But when it is re-inserted into the page, bootstrap is no longer aware of it and the affixing behavior breaks.

At this point, I think I have a few options, any of which would solve this problem:

  • Is there a smart way to call Jquery from within a Vue component? I'm not using Jquery anywhere else, so would rather not.
  • Is there a way to force Bootstrap affixes to refresh?
  • Is there a way to force Vue to not cache this component, creating a new one every load?
  • Is there a better way of creating an affix with Vue?

Thanks!

Here is the Vue component of concern:

<template> <div id="funclist-affix" class="panel panel-default" data-spy="affix" data-offset-top="155"> <div class="panel-body"> <h4>Functions</h4> <div class="list-group function-list"> <router-link v-for="(func,line) in functions" :key="line" :to="'#' + func.name" :class="['list-group-item', 'code', {uncovered: func.uncovered}]" :title="func.name">{{ func.name }}</router-link> </div> </div> </div> </template> <script> export default { name: 'functionList', data () { return { } }, props: ['functions'] } </script> <style> a { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } #funclist-affix { max-height: calc(100% - 2 * 20px); overflow-y: auto; } </style>
Categories: Software

Pages