Software
FeathersJS and VueJS 2 coexistence (repo)
I want a simple way to have scaffolded versions of feathers and vue, where they both use their -cli utilities, but in such way they don't mess with each other, but can be deployed at once. Requisites:
- I don't feathers-js to recompile things because something changed in the vue sub-folder.
- I want to deploy everything to heroku and build as it is just one thing (that is, only one "package.json", only one "npm start".
- I want to use express capabilities of feathers to not only provide the rest/sockets services but also, serve the html/vue-bundled-js.
I've seen several examples where you just create one "server" and one "client" folder, which is great for separation between client-server, but then... how do you include the vue app bundle into the feathers served static (public) and to make all happen seamlessly.
Also please let me know if I'm wrong with any of my "requirements" (a.k.a.: I should change my mindset).
How to seperate Vue logic in a laravel app based on layout and page templates
I have a laravel app and a Vue instance attached to the body (or a div, just inside the body).
const app = new Vue({ el: '#app' });I think it makes sense to use the Vue instance for stuff relating to the layout (eg header, nav, footer logic).
Now I have a form that is visible on a specific route (e.g. example.com/thing/create). I want to add some logic to it, e.g. hiding a field based on selected option in the form. It is logic meant for just this form (not to be reused). I prefer not to put all the logic inline with the form but put it in the app.js. I could put it in the Vue instance bound to the body but that sounds odd as it only applies to the form that is much deeper into the dom.
I want to leave the markup of the form in the blade template (that inherits the layout).
I tried creating a component but am not sure how to bind this inside the main Vue instance. What is the best way to handle things for this form, put it in the app.js and have it somewhat structured, putting the variables somewhat into scope. Or is it really necessary to remove the main Vue instance bound to the full layout code?
What I tried was something like this, but it does not work (attaching it to the <form id="object-form"> seems to fail:
var ObjectForm = { template: function() { return '#object-form'}, data: function() { return { selectedOption: 1 } }, computed: { displayField: function() { // return true or false depending on form state return true; } } };Things do work if I remove the #app Vue instance or when I put everything directly in the app Vue instance. But that seems messy, if I have similar variables for another form they should be seperated somewhat. I would appreciate some advice regarding the structure (differentiate page layout and page specific forms) and if possible some example to put the form logic inside the main app.js.
Testing API call in Vue with Moxios
I am having trouble figuring out how to test an API call that happens in the "mounted" lifecycle hook.
I have a single file component that is responsible for displaying some information about an "Owner".
This works exactly how I want / expect in the browser.
<template> <div> <h3>Owner Information</h3> <table class="table table-striped table-condensed"> <thead> <th>Name</th> <th>Address</th> <th>Social Security Number</th> <th>Ownership Percentage</th> </thead> <tbody> <tr :data-owner-id="owner.id" v-for="owner in owners"> <td>{{ owner.name }}</td> <td>{{ owner.address }}</td> <td>{{ owner.censored_ssn }}</td> <td>{{ owner.ownership_percentage }}</td> </tr> </tbody> </table> </div> </template> <script> import axios from 'axios'; export default { data() { return { principal_id: '', owners: [] } }, mounted() { const el = document.querySelector('#owner-information'); this.principal_id = el.dataset.principal; var self = this; axios.get(`/principals/${this.principal_id}.json`).then(response => { response.data.owners.map((owner) => { owner.score = ''; owner.link = ''; owner.last_pull_date = ''; self.owners.push(owner); }); }); .catch(e => { console.log(e); }); } } </script>For testing, I am using Karma, Jasmine, and Avoriaz.
Here is a failing test:
import { mount } from 'avoriaz' import OwnerInformation from '../../app/javascript/packs/OwnerInformation.vue' describe('OwnerInformation', () => { let component beforeAll(() => { const element = document.createElement('div') element.setAttribute('id', 'owner-information') element.setAttribute('data-principal', '84033') document.body.appendChild(element) component = mount(OwnerInformation) component.vm.$mount('#owner-information') }) it('retrieves owner information from the API', () => { expect(component.data().owners.length).toBe(1) }) })The above expects 1, but gets 0.
So now I figure that I need to stub/mock out my API request in some manner. A quick Google search leads me to moxios. So I install it with Yarn and eventually come up with this. I am not 100% sure where to put moxios.stubRequest, but have tried putting it in beforeAll(), beforeEach(), and inside the "it".
```
import moxios from moxios import { mount } from 'avoriaz' import OwnerInformation from '../../app/javascript/packs/OwnerInformation.vue' describe('OwnerInformation', () => { let component beforeAll(() => { const element = document.createElement('div') element.setAttribute('id', 'owner-information') element.setAttribute('data-principal', '12345') document.body.appendChild(element) component = mount(OwnerInformation) component.vm.$mount('#owner-information') }) beforeEach(() => { moxios.install() }) afterEach(() => { moxios.uninstall() }) it('retrieves owner information from the API', () => { moxios.stubRequest('/principals/12345', { status: 200, response: { id: 1, owners: [ { name: 'Test Owner', address: '123 Test St.', ssn: '123-12-1234', ownership_percentage: 100 } ] } }) expect(component.data().owners.length).toBe(1) })It appears that the request is not actually be stubbed out. To troubleshoot, I put a console.log statement just before the axios.get() call (which logs out successfully) and I also put a console.log to log out the response, but this one never shows up which makes me think that the axios request is not working and is not getting "intercepted" by moxios.
... console.log('CALLING API...') axios.get(`/principals/${this.principal_id}.json`).then(response => { console.log('***********************') ...When I run the test I do see a 404, but am unsure why:
01 08 2017 12:49:43.483:WARN [web-server]: 404: /principals/12345.json
To me, it makes most sense to stub out the request at the top of beforeAll(), but this does not work either.
How can I arrange this so that moxios stubs out the API request and it returns so that my test passes?
Handling form submission without replacing template in VueJS
First of all, please be kind. I'm new to VueJS coming from the Angular world where things are different ;-)
I am creating a multi-page website using VueJS for simple things like a floaty header and submission of forms etc. I'd like the markup for my contact form to be in my HTML (rendered by the CMS) and I'd like to have VueJS handle the form submission and replacing the form with a thank-you message. So, a simplified version of the form would look like this.
<contact-form> <form class="contact-form_form"> ... <input name="emailaddress" type="text" /> ... <button></button> </form> <div class="contact-form_thanks"> Thanks for filling in this lovely form </div> </contact-form>So, the obvious thing to do is to create a VueJS component, but I don't want it to introduce a new template, I just want it to submit the form when the button is pressed (using Axios) and hide the form and show the thank you message.
I know how to do all of this in angular using attribute directives and ng-show/hide etc. but can't really see how to do this in VueJS because all the tutorials are geared to wards SPAs and Single file components with templates.
Any kick in the right direction would be appreciated.
Can't understand this Vuex error coming from Axios request
I'm using axios to post two requests to update a user profile in my app:
methods: { updateProfileInfo () { let token = this.getAuthToken return axios.patch(`/api/profiles/${this.userid}/`, { bio: this.bio, dob: this.dob, media_url: this.media_url }, { headers: { 'Authorization': 'Token ' + token } }) }, updateUserInfo () { let token = this.getAuthToken return axios.patch(`/rest-auth/user/`, { username: this.username, first_name: this.firstname, last_name: this.lastname }, { headers: { 'Authorization': 'Token ' + token } }) }, updateProfile () { axios.all([this.updateProfileInfo(), this.updateUserInfo()]) .then(axios.spread(function (resProfile, resUser) { this.$store.commit('SET_USERNAME', this.username) console.log('spread...') console.log(resProfile) console.log(resUser) })).catch(err => { console.log(err) }) }This is generating the following error (trying to commit username inside updateProfile):
TypeError: Cannot read property '$store' of null at eval (Profile.vue?bbca:206) at wrap (spread.js?3c41:25) at <anonymous>Here are my mutations in the Vuex store:
mutations: { SET_TOKEN_AUTH(state, key) { state.token = key }, SET_USERID(state, id) { state.userid = id }, SET_USERNAME(state, username) { state.username = username }, USER_LOGOUT(state) { state.token = null state.userid = null state.username = null } },vuejs - dynamic input 'types'
I would like to be able to dynamically change the type of an input field between text and password. I tried doing the following:
<input :type="dynamicInputType"> data() { return { dynamicInputType: 'password' } }But apparently this doesn't work; vuejs displays the error: v-model does not support dynamic input types. Use v-if branches instead.
It's not clear to me how I can fix this with v-if.
Vue.js Async component - file promise rejected
I am trying to solve a strange error. After several hours, I have no idea what is wrong.
I create a component in the template that is supposed to be async:
<div id="app"> <component :is="componentType"></component> </div>module.js:
Vue.component('login-form', function (resolve, reject) { require(['./login-form'], resolve) });This works well on all pages except when I want to show a password reset page.
The link where the component loading fails is: test.localhost/password-reset/token?email=email@email.com
This is what I see in the Chrome console:
Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}__proto__: Promise[[PromiseStatus]]: "rejected"[[PromiseValue]]: Error: Loading chunk 0 failed. at HTMLScriptElement.onScriptComplete (http://test.localhost/js/manifest.js:104:24)Any ideas what might be wrong? The same thing works everywhere except this one page. Thanks!
How to edit tweet styling using node package vue-tweet-embed in vuejs?
How to use node package vue-tweet-embed in vuejs2?
This is building off the question above. I have code that works to generate the tweets I want but I can't get it to style how I want (especially on mobile, its too small). I've tried a few different styling things but none of them edit the tweet. Literally nothing in the .tweet{} styling or the commented code after changed anything. I would like it to fill the width of the phone increase text size on mobile. Help? Thanks!
<template> <div> <component-view :id="'891397134662193152'" class="tweet"></component-view> </div> </template> <script> export default { name: 'email', components: { 'component-view': Tweet }, } </script> <style scoped> .tweet { font-size: 30px; background-size: 600px; width:100%; margin:0 auto; max-width: 1000px; } /*.tweet a { font-size: 70px; font-weight: normal; line-height: 20px; }*/ /*.tweet p.Tweet-text.e-entry-title { width:100% !important; }*/ </style>Vue.js changes data values by itself
This might sound really strange, but it seems Vue decided to change data values by itself. I have a component :is="currentView" tag. I initially set the currentView data to loading and then change it to authenticate later if a condition is met. This works fine. But when a use has authenticated and I change currentView to loading while authenticating the user, it loads for 0.1 seconds and then shows the authenticate component and does that once more, then it shows the component that it should after authenticating. If I log currentView after setting it to loading it logs authenticate and then loading with around 100 milliseconds in between. I can guarantee that I never set currentView to authenticate by myself.
Any ideas?
Vue.js components + Laravel right management
I'm unsure how to procede with using Vue single file components alongside Laravel's right management plugins. In general I'm loading the components on different pages, however different actions in components require different rights available, and passing the available rights directly to component seems kind of unsafe. What would be the correct approach here?
Vuejs unit test - watcher on props
I'm trying to unit test a watcher on a props in a Vue component. I'm using Karma+Jasmine. But it seems that watchers on props are not triggered in unit test.
Here is a simple component :
export default { name: 'hello', data: function () { return { b: null }; }, props: { a: { type: String, default: null } }, watch: { a(val) { this.b = val; } }, computed: { c() { return this.a + " computed"; } } }and here is my test :
describe('Hello', () => { const HelloCtor = Vue.extend(Hello); let vm; beforeEach(() => { vm = new HelloCtor({ propsData: { a: "hello" } }).$mount(); }); afterEach(() => { vm.$destroy(); }); it('should watch a and compute c', (done) => { vm.$nextTick(() => { expect(vm.c).toBe("hello computed"); expect(vm.b).toBe("hello"); done(); }); }); });In the asserts, 'c' is correctly computed but 'b' is always null. If I move 'a' to data everything works perfectly. Note that when I test my app manually in my browser, watchers on props are triggered just like the ones on data variable.
Any ideas on how to test it ?
New Test Pilot Experiments Available Today
It’s been a busy summer for Firefox! Last month, we delivered the first in a series of groundbreaking updates to the browser. This week, the Test Pilot team is continuing to evolve Firefox features with three new experiences that will make for a simpler, faster and safer experience.
SendSending files over the internet is something many of us do everyday. Mozilla makes it easy to keep your files safe. With Send, your files self-destruct after download, so they can’t be accessed by anyone else. Your files are encrypted during transmission. Plus, Send encrypts files on the client side, so that not even Mozilla can read them.
Mozilla is a champion of making the web open and accessible to everyone. With Voice Fill, we’re experimenting with support for Speech to Text (STT) functionality in Firefox, making it possible for users to input text in Firefox by voice. Your contributions to this experiment will help us optimize speech to text input so that we can expand support throughout Firefox.


Whether it’s a sticky note, an app or the back of an envelope, so many of us rely on jotting down quick notes to keep track of our busy lives. Notes is a simple, convenient place to take, store and retrieve notes – all within Firefox. We’re also working to build in support for Firefox Accounts, so you can sync your notes wherever you use Firefox
The Test Pilot program is open to all Firefox users and helps us test and evaluate a variety of potential Firefox features. To activate Test Pilot and help us build the future of Firefox, visit testpilot.firefox.com.
These Test Pilot experiments are available in English only. If you’ve experimented with Test Pilot features before, you know that you might run into some bugs or lose some of the polish in Firefox, so you can easily enable or disable features at any time.
We want your feedback! Try out these and other Test Pilot experiments and help us decide which new features to build into future versions of Firefox.
The post New Test Pilot Experiments Available Today appeared first on The Mozilla Blog.
Vue.js not all transition group children are animating
This is the transition group that I am using
<article class="hotel-row" v-for="hotel in paginatedHotels" :key="hotel.hotelid"> <search-hotel :hotel="hotel"></search-hotel> </article>Vue will throw an error if I do not key the children:
[Vue warn]: children must be keyed:
No problem I add my unique hotelid to make sure Vue can make a distinction between elements.
I have a list of 25 hotels and the problem is that when I keyed my child elements that the elements that were in my first 25 results and also in the results after updating my list of hotels do not animate.
Vue apparently tracks these now with the :key and does not find it needed to animate these children.
I am guessing this happens because there are already part of the list so why animate them again? My list can totally re-order though so I would prefer to always have all items animate.
I can clearly see that the transition classes are not added to elements that are the same before and after my transition.
How can I make sure all elements are animated though?
Could not resolve view with name 'HelloWorld' in servlet with name 'dispatcherServlet'
I started study Spring Boot just.
I want to display html page .
But It doesn't work.
If I change HelloWorld.html to HelloWorld.ftl . I can display ftl page ,but the vue.js is not resolve file .
below my Spring boot configure File and Controller.
application
spring.resources.chain.strategy.content.enabled=true spring.resources.chain.strategy.content.paths=/** spring.mvc.view.prefix=/ spring.mvc.view.suffix=.html spring.mvc.static-path-pattern=/**Resources
static/js/vue.js
tempates/HelloWorld.html
Controller
@Controller public class HelloController { @RequestMapping("/hello") public String hello(){ return "HelloWorld"; } }How to scroll to specific data value in Vue?
I have simple table in Vue:
<tbody> <tr v-for="(item, index) in items"> <td> ... </td> </tr> </tbody>The items are dynamically adding via unshift. The main thing is that I need to navigate through table via up, down keys so I did it like this:
jQuery(document).keydown((e) => { const which = e.which; if ([38, 40].indexOf(which) != -1) { e.preventDefault(); if (this.active_index == null) { this.active_index = 0; } else { if (e.which == 38) { // up this.active_index--; } else { // down this.active_index++; } } console.log(this.items[this.active_index]) } });Is it possible somehow to get this.items[this.active_index] element or its position to scroll to it.
How to prevent/stop propagation of default event (click) in directive (vue 2.x)
usage
<button @click="handleClick" v-login-to-click>CLICK</button>handleClick is always triggered. How I can prevent that from directive? Tried with/without addEventListener "capture" flag without any luck.
Change image source (twice) when src does not exist
I just started using Vue in the front-end of my website. In one of my Vue-components I want an image with a certain path:
<img src="path/example/with/vue/var">Now, this is what I want to do:
- Check if the file in "path/example/with/vue/var" exists
- If not: Change the src to "another/path/with/vue/var"
- Check if "another/path/with/vue/var" exist
- If not: Change the src to "default/path"
I already tried to use onerror with a function inside of it. But the problem is I'm loading 100+ objects with a couple of images for each object. If I just check if the file exists the normal way(through ajax or with a XMLHttpRequest), the performance is completely gone. All objects are loaded through a JSON file.
I hope you guys understand the question. Thanks!
how to use listeners in vue.js for events like scroll and windows resizing
Hello i am learning vuejs and was converting one of my projects into vuejs i wanted to know that i can write my custom functions in methods and call those in mounted hook i wanted to know how do i use listeners in vuejs.
also can i used my jquery by importing in vue project
The event listener documentation on vue website states only v-on and click example but no examples are for windows listeners
jQuery(document).ready(function(){ //cache DOM elements var mainContent = $('.cd-main-content'), header = $('.cd-main-header'), sidebar = $('.cd-side-nav'), sidebarTrigger = $('.cd-nav-trigger'), topNavigation = $('.cd-top-nav'), searchForm = $('.cd-search'), accountInfo = $('.account'); //on resize, move search and top nav position according to window width var resizing = false; moveNavigation(); $(window).on('resize', function(){ if( !resizing ) { (!window.requestAnimationFrame) ? setTimeout(moveNavigation, 300) : window.requestAnimationFrame(moveNavigation); resizing = true; } }); //on window scrolling - fix sidebar nav var scrolling = false; checkScrollbarPosition(); $(window).on('scroll', function(){ if( !scrolling ) { (!window.requestAnimationFrame) ? setTimeout(checkScrollbarPosition, 300) : window.requestAnimationFrame(checkScrollbarPosition); scrolling = true; } }); //mobile only - open sidebar when user clicks the hamburger menu sidebarTrigger.on('click', function(event){ event.preventDefault(); $([sidebar, sidebarTrigger]).toggleClass('nav-is-visible'); }); //click on item and show submenu $('.has-children > a').on('click', function(event){ var mq = checkMQ(), selectedItem = $(this); if( mq == 'mobile' || mq == 'tablet' ) { event.preventDefault(); if( selectedItem.parent('li').hasClass('selected')) { selectedItem.parent('li').removeClass('selected'); } else { sidebar.find('.has-children.selected').removeClass('selected'); accountInfo.removeClass('selected'); selectedItem.parent('li').addClass('selected'); } } }); //click on account and show submenu - desktop version only accountInfo.children('a').on('click', function(event){ var mq = checkMQ(), selectedItem = $(this); if( mq == 'desktop') { event.preventDefault(); accountInfo.toggleClass('selected'); sidebar.find('.has-children.selected').removeClass('selected'); } }); $(document).on('click', function(event){ if( !$(event.target).is('.has-children a') ) { sidebar.find('.has-children.selected').removeClass('selected'); accountInfo.removeClass('selected'); } }); //on desktop - differentiate between a user trying to hover over a dropdown item vs trying to navigate into a submenu's contents sidebar.children('ul').menuAim({ activate: function(row) { $(row).addClass('hover'); }, deactivate: function(row) { $(row).removeClass('hover'); }, exitMenu: function() { sidebar.find('.hover').removeClass('hover'); return true; }, submenuSelector: ".has-children", }); function checkMQ() { //check if mobile or desktop device return window.getComputedStyle(document.querySelector('.cd-main-content'), '::before').getPropertyValue('content').replace(/'/g, "").replace(/"/g, ""); } function moveNavigation(){ var mq = checkMQ(); if ( mq == 'mobile' && topNavigation.parents('.cd-side-nav').length == 0 ) { detachElements(); topNavigation.appendTo(sidebar); searchForm.removeClass('is-hidden').prependTo(sidebar); } else if ( ( mq == 'tablet' || mq == 'desktop') && topNavigation.parents('.cd-side-nav').length > 0 ) { detachElements(); searchForm.insertAfter(header.find('.cd-logo')); topNavigation.appendTo(header.find('.cd-nav')); } checkSelected(mq); resizing = false; } function detachElements() { topNavigation.detach(); searchForm.detach(); } function checkSelected(mq) { //on desktop, remove selected class from items selected on mobile/tablet version if( mq == 'desktop' ) $('.has-children.selected').removeClass('selected'); } function checkScrollbarPosition() { var mq = checkMQ(); if( mq != 'mobile' ) { var sidebarHeight = sidebar.outerHeight(), windowHeight = $(window).height(), mainContentHeight = mainContent.outerHeight(), scrollTop = $(window).scrollTop(); ( ( scrollTop + windowHeight > sidebarHeight ) && ( mainContentHeight - sidebarHeight != 0 ) ) ? sidebar.addClass('is-fixed').css('bottom', 0) : sidebar.removeClass('is-fixed').attr('style', ''); } scrolling = false; } });The width of columns in a table change when a row of input boxes is added dinamically
The table before the row with input-boxes is shown As you see in the image above, there is a table that contains on the first row, a button for showing/hiding the row that contains input-boxes like in the image below.
The table where the row with input boxes is shown
The problem is that the width of the columns is changed when the row that contains input-boxes is displayed. (It can be seen from the images the difference of width's columns, before and after)
And the width of the input-boxes is set to 100%.
Also the padding and border are not changed, only the width of td.
So the question is, how can I mentain the same width of the columns, without setting a fixed width, like in the code below?
And also adding white-space: nowrap doesn't work!
Here is the part of the code for showing the row with the input-boxes.
<tr v-if="showFilters"> <td v-for="key in filterKeys" v-if="key.visible"> <div class="input-group"> <pf-text-field v-model="key.value" tooltip="Filter"> </pf-text-field> </div> </td> </tr>Vue 2 - vuex mapGetters and pass params
Is it possible to pass params with mapGetters?
I have this in main Vue instance:
computed: { filterAuthors() { return this.$store.getters.filterAuthors(this.search.toLowerCase()); } }this.search is bind to the input field via v-model="search=, and in my Vuex instance I have this getters:
getters: { filterAuthors: (state) => (search) => { return state.authors.filter((author) => { return author.name.toLowerCase().indexOf(search) >= 0; }) } },This one is working fine, but I am trying to find a way (if it is possible) to use mapGetters and to pass the argument. Can this be done?