Advanced Frontend Webapp Architecture With Laravel and Vue JS

Advanced Frontend Webapp Architecture With Laravel and Vue JS

Advanced Frontend Webapp Architecture With Laravel and Vue JS

ATTENTION: Vue’s Vue-Router sub-project has come out with an update that fills most of the functionality in this article.

You can now use this.$router.app at any time inside a component to access the main component. Check it out here: http://router.vuejs.org/api/properties.html. And, Vue now has events built in. So I can say this.$dispatch(‘foo’) to run methods on other components. Haven’t played with it much but it looks really cool. http://vuejs.org/api/instance-methods.html#Events.

Vue JS 2 - The Complete Guide (incl. Vuex)

That said the rest of this article teaches important skills in front-end applications and is still a good read.

Do you use Laravel PHP and Vue JS? Do you wish there was a better way to structure your applications you build? This tutorial is just for you! In it, we set up simple two-way communication between the different components of your front-end app.

Would you like to get the results of this tutorial without reading through it? Check out Laravue, the brand new boilerplate repo for starting off!

This tutorial is inspired by a video by Laracasts that sets up the basic app architecture. You don’t have to watch it, but here’s a link if you’re curious: https://laracasts.com/series/learning-vuejs/episodes/9

To sum up the result of the video, you have two directories and one main file: resources/assets/js/components/ , resources/assets/js/views/ , and resources/assets/js/app.js. In the components folder you have two files for each component: Component.js and component.template.html . Component.js is the model while component.template.html is the view. You do the same for views/, with about.js and about.template.html . You export all of this using module.exports to package the functioanlity. If you use coffeescript, name them Component.coffee and view.coffee. Simple stuff.

In app.js, you include all of these into the components object of your main View-Model. The views are named like ‘name-view’ and the components like ‘name’. You also have a currentView variable in the data object, which represents the view that should be displayed. To display all that, you use .

Alright, now that you’ve finished that, you should have a great architecture to start off with. You have your main app.js file (which will now be called app), individual views, and components. However, there’s a few things that are missing:

  1. a standard way to communicate from app -> view
  2. a standard way to communicate from view -> app
  3. a standard way to communicate from components -> view
  4. a standard way to communicate from components -> app

There’s a few important things missing from basic Vue and Laravel integrations.
Why would we want these features? Suppose we want to change the currentView from within a view. Right now, there’s no easy way to do that. Using my setup, we can just run this.app.currentView = ‘awesome-view’; .

Another example is if you want to have one user object that can be accessed application-wide. Just add it to the data object of your main app and it can be accessed from views using this.app.user !

To make components easier to understand, let’s think of vue components just like classes in PHP: each view and component is like a class that is then instantiated into objects through ’s or a .

There’s a few important things missing from basic Vue and Laravel integrations.
A quick note on components: when I say it sometimes I mean a component in general, other times I mean non-view, new DOM element components. Like the ones in the components/ folder. It should be pretty clear when I’m talking about which one, contact me if you have any ways I can make it more clear.

Now that we understand the basics of components, let’s try and get a (even) better architecture for setting them up and addressing the problems above. Let’s think about Laravel: there’s a main IoC container, which is accessed through the App facade, which contains various smaller classes called Service Containers. This is starting to sound really similiar to the front end: we have a main app that contains our smaller components & views (which are really just glorified components).

In Laravel, each service provider can access the IoC container through $this->app. What if we could do the same thing in views, saying this.app? Well it turns out you can!

There’s a few important things missing from basic Vue and Laravel integrations.
With this technique, the app variable is passed easily into each view using two-way binding. This means you can change the master application from a view, and the changes are reflected application-wide on the app view-model itself, every view, and every component.

Part 1: using this.app in each view

There’s a few important things missing from basic Vue and Laravel integrations.
First, let’s go to the main HTML file that contains the <component is=“{{ currentView}}”>. We need to add the app as a prop to that. So, change that to <component is=“{{currentView}}” app=“{{@ app }}”> .

If you’ve used Vue before you’ll be familiar with the mustache syntax, but the {{@ might leave you a little confused. Basically, it says pass the app into the component, but if the component makes a change to the app, reflect it in the scope that contains the component too. In other words it enforces two-way binding. If you didn’t have the @, you could do something to the app in the view and then nothing would happen anywhere else!

Of course, if you are in a .blade.php file, change that to <component is=“@{{currentView}}” app=“@{{@ app }}”> so Laravel doesn’t get confused and try to look for a currentView and app constant.

Also, in order to make things run better, you may want to add keep-alive to the end of the tag. It basically keeps the current view alive in the background instead of deleting it, so if you change currentView back to it Vue doesn’t have to do more work. However, if you want to get updated data anytime the user changes views, it would be very easy to just remove keep-alive so that the ready method is recalled on the component.

Next, we need to make sure that app is added a valid props array for each view. In the module.exports array, go add an array called props if it does not already exist. Next, add a string called ‘app’ to it. Here’s an example:

gistfile1.js

module.exports = {
    props: [
        'app'
    ],
    template: require('./analytics.template.html')
};

Finally, we need to configure our app.js file to have an app variable that points to itself. Add app: {} to its data object. Then, add a createdmethod to the app. In it, say this.app = this; . You’re done! You now have access to the master app in each view.

Why a created method, instead of a ready method, you may ask? Because created is called before the DOM is evaluated, meaning Vue doesn’t even know the components have been instantiated yet. What this all amounts to is that the app variable is ready the moment the views are!

If you need access to the master app in a component, you need to pass it in as a prop. In the component’s module.exports, add ‘app’ to the props array. Then, just like before, whenever you instantiate the component using app=“{{@ app }}” . You can use this for any component.

Part 2: setting data for a particular view from other views or the main app

Since components are only loaded if you have component is set to them at one point in the app’s lifecycle, you can’t reliably access them directly from this.app. Instead, you can set data for them in this.app then pull it in the views. This is easier than it sounds! In app.js, add a new object to the data object, and call it viewData. In it add a name of each view you want to set data for and point it to an empty object. Example:

gistfile1.js

data: {
	currentView: 'edit-view',
	app: {},
	viewData: {
		'edit-view': {},
		'about-view': {}
	}
}

To set that data from a view, just go this.app.viewData[‘about-view’][‘foo’] = ‘bar’; . Then, to get it from the about-view, just go this.app.viewData[‘about-view’][‘foo’]. You could also shorten that by going into the ready method and adding: this.external = this.app.viewData[‘about-view’]. Be sure to add external as an empty object to the data function. Now you can just say this.external.foo to access it. Example:

gistfile1.js

module.exports = {
    data: function() {
        return {
            external: {}
        };
    },

    props: [
        'app'
    ],

    template: require('./analytics.template.html'),

    ready: function() {
        this.external = this.app.viewData['analytics-view'];

        //Access variable "downloads" that has been set in about-view
        alert(this.external.downloads);

        //Access the user variable from the main app
        alert(this.app.user.name);
    }
};

This part really is just an example of taking advantage of the global access to the app’s data, nothing more. So take it with a grain of salt, because the real power is in Part 1 and 3.

Part 3: calling view functions

This is undoubtedly the most involved yet most useful part of this tutorial. For example, if I have a search bar in my navbar component, yet want to call a function in the search-results view, there is no good way to do it until now.

We need to be able to call functions if a view has been instantiated and if it hasn’t been. If it has been, we can just say viewModelfunctionName. If it hasn’t, doing so will result in an error. So we need to account for both situations…

Let’s add an setting to each view’s data in app.js called ready. Make it to default to false. Then, in the ready() function in each view, say this.external.ready = true; . Next, add an array called funcs_to_call . If the view has not been instantiated yet, we can add the name of the function to the array so the view can call it later in its ready() method.

To call the function on another view, we can say t_his.app.call(‘search-view’, ‘search’);_ This will call search-view.search() . If the view is instantiated, we can just call it directly. Otherwise, we have a little bit of a harder job.

Let’s deal with the first scenario first. Each view in viewData we need to have ready, funcs_to_call, and model. In each view’s ready() function, we need to set ready to true and model to this. Example:

gistfile1.js

ready: function() {
    this.app.viewData['analytics-view'].ready = true;
    this.app.viewData['analytics-view'].model = this;
}

This allows us to call the functions easily. In app.js, lets add a new method to the methods object called call(). Look at the gist below to see how it works:

gistfile1.js

methods: {
    call: function(view, name) {
    	if(this.viewData[view].ready == true) {
    		this.viewData[view].model[name]();
    	}
    }	
}

Basically, it just tests if the view is ready. If it is, then it calls it using array syntax magic. Let’s do a test of our own: go to analytics-view.js and replace it to the following code:

gistfile1.js

module.exports = {
    data: function() {
        return {
            external: {}
        };
    },

    props: [
        'app'
    ],

    template: require('./analytics.template.html'),

    ready: function() {
        
        this.app.viewData['analytics-view'].ready = true;
        this.app.viewData['analytics-view'].model = this;

        this.app.call('analytics-view', 'al');
    },

    methods: {
        al: function() {
            alert('i got called!');
        }
    }
};

When you load the page, it should instantly pop up with ‘i got called!’ as soon as the view is set in currentView!

Now we need to figure out what to do if ready is set to false. First, we just need to add the method name to the array, right? Add an else statement to the call method in app.js to push the function name onto an array:

gistfile1.js

else {
	this.viewData[view].funcs_to_call.push(name);
}

Now we just need to check on ready() functions if there’s anything on the funcs_to_call array and call them if they exist. Add this to the end of the ready() function:

gistfile1.js

var methods = this.app.viewData[view].funcs_to_call;
for(var i in methods)
{
    this[methods[i]]();
}

Now, when the view is loaded, it runs the method that was called!!!

Closing

To close it up, here’s the two files we’ve been working on, completed and done.

gistfile1.html

...
<body id="mainApp">
	<component is="@{{ currentView }}" app="@{{@ app }}" keep-alive></component>
</body>
...
var Vue = require('vue');

var app = new Vue({
	el: 'body#mainApp',

	data: {
		currentView: 'loading-view',
		app: {},
		viewData: {
			'edit-view': {
				ready: false,
				funcs_to_call: [],
				model: {}
			},
			'analytics-view': {
				ready: false,
				funcs_to_call: [],
				model: {}
			}
		}
	},

	components: {
	    // Views
		'analytics-view': require('./views/analytics'),
		'edit-view': require('./views/edit'),
		
		// Components
		'piece': require('./components/Piece')
	},

	methods: {
		call: function(view, name) {
			if(this.viewData[view].ready == true) {
				this.viewData[view].model[name]();
			} else {
				this.viewData[view].funcs_to_call.push(name);
			}
		}	
	},

	ready: function() {
	this.app = this;
		
        this.app.call('analytics-view', 'al'); //Test caling the al function
	}
});

module.exports = {
    data: function() {
        return {
            external: {}
        };
    },

    props: [
        'app'
    ],

    template: require('./analytics.template.html'),

    ready: function() {
        var view = 'analytics-view';
        this.app.viewData[view].ready = true;
        this.app.viewData[view].model = this;

        var methods = this.app.viewData[view].funcs_to_call;
        for(var i in methods)
        {
            this[methods[i]]();
        }
    },

    methods: {
        al: function() {
            alert('i got called!');
        }
    }
};

You can use these two files as templates when using this design architecture in the future! I know I will.

To the left is the file structure I have for the Laravue repo. There are a couple of differences though: 1) I have a home view not an analytics view, and 2) I use coffeescript instead of vanilla JS. These aren’t biggies though!

What now?

In the future, I’ll no doubt be optimizing this and making it better. If you have any suggestions, just leave a response below! Your input is essential because the only way this can thrive is through community involvement.

There’s a few important things missing from basic Vue and Laravel integrations.
In the future I may make a way to combine the ready and model variables in viewData functionally into one. But the additional code required may be more than I actually save, so I’m not sure on this one.

Something else I feel like this needs is a CLI. How about maybe php artisan make:view analytics and it will add all this boilerplate? Just an idea. Let me know if you’re interested in doing anything like this, because I think might be a bit beyond me.

For more info on how calling functions on objects using a string check out http://stackoverflow.com/questions/9854995/javascript-dynamically-invoke-object-method-from-string . It helped me out allot.

UPDATE: allow for arguments passed into view methods!

// app.js call method.
call: function(view, name, args = []) {
	if(this.viewData[view].ready == true) {
		this.viewData[view].model[name](args);
	} else {
		this.viewData[view].funcs_to_call.push({name: name, args: args});
	}
}

// updated for loop inside each view
for(var i in methods)
{
    this[methods[i].name](methods[i].args);
}

Now you can do this.app.call(‘foo’, ‘bar’, [‘arg1’, ‘arg2’, ‘arg3’]) and it will pass the array into the method. To retrieve them in a method just do args[0], args[1], args[2].

If you’re using coffeescript, it’s even easier! You can just use the … syntax for arguments. Yes, it’s technically possible without coffee, but it would look pretty ugly… Anyways here’s the coffeescript example:

call: (view, funcName, args...) ->
	if   @views[view].ready then @views[view]['model'][funcName].apply(null, args)
	else @views[view].funcs.push({name: funcName, args: args}) 

Any input is highly welcome!

30s ad

Vue JS 2 - The Complete Guide (incl. Vue Router & Vuex)

Build A Web App with VueJS, Spring Framework and MongoDB

Vue JS 2.0 - Mastering Web Apps

Vue JS 2: From Beginner to Professional (includes Vuex)

The Ultimate Vue JS 2 Developers Course

ATTENTION: Vue’s Vue-Router sub-project has come out with an update that fills most of the functionality in this article.

You can now use this.$router.app at any time inside a component to access the main component. Check it out here: http://router.vuejs.org/api/properties.html. And, Vue now has events built in. So I can say this.$dispatch(‘foo’) to run methods on other components. Haven’t played with it much but it looks really cool. http://vuejs.org/api/instance-methods.html#Events.

Vue JS 2 - The Complete Guide (incl. Vuex)

That said the rest of this article teaches important skills in front-end applications and is still a good read.

Do you use Laravel PHP and Vue JS? Do you wish there was a better way to structure your applications you build? This tutorial is just for you! In it, we set up simple two-way communication between the different components of your front-end app.

Would you like to get the results of this tutorial without reading through it? Check out Laravue, the brand new boilerplate repo for starting off!

This tutorial is inspired by a video by Laracasts that sets up the basic app architecture. You don’t have to watch it, but here’s a link if you’re curious: https://laracasts.com/series/learning-vuejs/episodes/9

To sum up the result of the video, you have two directories and one main file: resources/assets/js/components/ , resources/assets/js/views/ , and resources/assets/js/app.js. In the components folder you have two files for each component: Component.js and component.template.html . Component.js is the model while component.template.html is the view. You do the same for views/, with about.js and about.template.html . You export all of this using module.exports to package the functioanlity. If you use coffeescript, name them Component.coffee and view.coffee. Simple stuff.

In app.js, you include all of these into the components object of your main View-Model. The views are named like ‘name-view’ and the components like ‘name’. You also have a currentView variable in the data object, which represents the view that should be displayed. To display all that, you use .

Alright, now that you’ve finished that, you should have a great architecture to start off with. You have your main app.js file (which will now be called app), individual views, and components. However, there’s a few things that are missing:

  1. a standard way to communicate from app -> view
  2. a standard way to communicate from view -> app
  3. a standard way to communicate from components -> view
  4. a standard way to communicate from components -> app

There’s a few important things missing from basic Vue and Laravel integrations.
Why would we want these features? Suppose we want to change the currentView from within a view. Right now, there’s no easy way to do that. Using my setup, we can just run this.app.currentView = ‘awesome-view’; .

Another example is if you want to have one user object that can be accessed application-wide. Just add it to the data object of your main app and it can be accessed from views using this.app.user !

To make components easier to understand, let’s think of vue components just like classes in PHP: each view and component is like a class that is then instantiated into objects through ’s or a .

There’s a few important things missing from basic Vue and Laravel integrations.
A quick note on components: when I say it sometimes I mean a component in general, other times I mean non-view, new DOM element components. Like the ones in the components/ folder. It should be pretty clear when I’m talking about which one, contact me if you have any ways I can make it more clear.

Now that we understand the basics of components, let’s try and get a (even) better architecture for setting them up and addressing the problems above. Let’s think about Laravel: there’s a main IoC container, which is accessed through the App facade, which contains various smaller classes called Service Containers. This is starting to sound really similiar to the front end: we have a main app that contains our smaller components & views (which are really just glorified components).

In Laravel, each service provider can access the IoC container through $this->app. What if we could do the same thing in views, saying this.app? Well it turns out you can!

There’s a few important things missing from basic Vue and Laravel integrations.
With this technique, the app variable is passed easily into each view using two-way binding. This means you can change the master application from a view, and the changes are reflected application-wide on the app view-model itself, every view, and every component.

Part 1: using this.app in each view

There’s a few important things missing from basic Vue and Laravel integrations.
First, let’s go to the main HTML file that contains the <component is=“{{ currentView}}”>. We need to add the app as a prop to that. So, change that to <component is=“{{currentView}}” app=“{{@ app }}”> .

If you’ve used Vue before you’ll be familiar with the mustache syntax, but the {{@ might leave you a little confused. Basically, it says pass the app into the component, but if the component makes a change to the app, reflect it in the scope that contains the component too. In other words it enforces two-way binding. If you didn’t have the @, you could do something to the app in the view and then nothing would happen anywhere else!

Of course, if you are in a .blade.php file, change that to <component is=“@{{currentView}}” app=“@{{@ app }}”> so Laravel doesn’t get confused and try to look for a currentView and app constant.

Also, in order to make things run better, you may want to add keep-alive to the end of the tag. It basically keeps the current view alive in the background instead of deleting it, so if you change currentView back to it Vue doesn’t have to do more work. However, if you want to get updated data anytime the user changes views, it would be very easy to just remove keep-alive so that the ready method is recalled on the component.

Next, we need to make sure that app is added a valid props array for each view. In the module.exports array, go add an array called props if it does not already exist. Next, add a string called ‘app’ to it. Here’s an example:

gistfile1.js

module.exports = {
    props: [
        'app'
    ],
    template: require('./analytics.template.html')
};

Finally, we need to configure our app.js file to have an app variable that points to itself. Add app: {} to its data object. Then, add a createdmethod to the app. In it, say this.app = this; . You’re done! You now have access to the master app in each view.

Why a created method, instead of a ready method, you may ask? Because created is called before the DOM is evaluated, meaning Vue doesn’t even know the components have been instantiated yet. What this all amounts to is that the app variable is ready the moment the views are!

If you need access to the master app in a component, you need to pass it in as a prop. In the component’s module.exports, add ‘app’ to the props array. Then, just like before, whenever you instantiate the component using app=“{{@ app }}” . You can use this for any component.

Part 2: setting data for a particular view from other views or the main app

Since components are only loaded if you have component is set to them at one point in the app’s lifecycle, you can’t reliably access them directly from this.app. Instead, you can set data for them in this.app then pull it in the views. This is easier than it sounds! In app.js, add a new object to the data object, and call it viewData. In it add a name of each view you want to set data for and point it to an empty object. Example:

gistfile1.js

data: {
	currentView: 'edit-view',
	app: {},
	viewData: {
		'edit-view': {},
		'about-view': {}
	}
}

To set that data from a view, just go this.app.viewData[‘about-view’][‘foo’] = ‘bar’; . Then, to get it from the about-view, just go this.app.viewData[‘about-view’][‘foo’]. You could also shorten that by going into the ready method and adding: this.external = this.app.viewData[‘about-view’]. Be sure to add external as an empty object to the data function. Now you can just say this.external.foo to access it. Example:

gistfile1.js

module.exports = {
    data: function() {
        return {
            external: {}
        };
    },

    props: [
        'app'
    ],

    template: require('./analytics.template.html'),

    ready: function() {
        this.external = this.app.viewData['analytics-view'];

        //Access variable "downloads" that has been set in about-view
        alert(this.external.downloads);

        //Access the user variable from the main app
        alert(this.app.user.name);
    }
};

This part really is just an example of taking advantage of the global access to the app’s data, nothing more. So take it with a grain of salt, because the real power is in Part 1 and 3.

Part 3: calling view functions

This is undoubtedly the most involved yet most useful part of this tutorial. For example, if I have a search bar in my navbar component, yet want to call a function in the search-results view, there is no good way to do it until now.

We need to be able to call functions if a view has been instantiated and if it hasn’t been. If it has been, we can just say viewModelfunctionName. If it hasn’t, doing so will result in an error. So we need to account for both situations…

Let’s add an setting to each view’s data in app.js called ready. Make it to default to false. Then, in the ready() function in each view, say this.external.ready = true; . Next, add an array called funcs_to_call . If the view has not been instantiated yet, we can add the name of the function to the array so the view can call it later in its ready() method.

To call the function on another view, we can say t_his.app.call(‘search-view’, ‘search’);_ This will call search-view.search() . If the view is instantiated, we can just call it directly. Otherwise, we have a little bit of a harder job.

Let’s deal with the first scenario first. Each view in viewData we need to have ready, funcs_to_call, and model. In each view’s ready() function, we need to set ready to true and model to this. Example:

gistfile1.js

ready: function() {
    this.app.viewData['analytics-view'].ready = true;
    this.app.viewData['analytics-view'].model = this;
}

This allows us to call the functions easily. In app.js, lets add a new method to the methods object called call(). Look at the gist below to see how it works:

gistfile1.js

methods: {
    call: function(view, name) {
    	if(this.viewData[view].ready == true) {
    		this.viewData[view].model[name]();
    	}
    }	
}

Basically, it just tests if the view is ready. If it is, then it calls it using array syntax magic. Let’s do a test of our own: go to analytics-view.js and replace it to the following code:

gistfile1.js

module.exports = {
    data: function() {
        return {
            external: {}
        };
    },

    props: [
        'app'
    ],

    template: require('./analytics.template.html'),

    ready: function() {
        
        this.app.viewData['analytics-view'].ready = true;
        this.app.viewData['analytics-view'].model = this;

        this.app.call('analytics-view', 'al');
    },

    methods: {
        al: function() {
            alert('i got called!');
        }
    }
};

When you load the page, it should instantly pop up with ‘i got called!’ as soon as the view is set in currentView!

Now we need to figure out what to do if ready is set to false. First, we just need to add the method name to the array, right? Add an else statement to the call method in app.js to push the function name onto an array:

gistfile1.js

else {
	this.viewData[view].funcs_to_call.push(name);
}

Now we just need to check on ready() functions if there’s anything on the funcs_to_call array and call them if they exist. Add this to the end of the ready() function:

gistfile1.js

var methods = this.app.viewData[view].funcs_to_call;
for(var i in methods)
{
    this[methods[i]]();
}

Now, when the view is loaded, it runs the method that was called!!!

Closing

To close it up, here’s the two files we’ve been working on, completed and done.

gistfile1.html

...
<body id="mainApp">
	<component is="@{{ currentView }}" app="@{{@ app }}" keep-alive></component>
</body>
...
var Vue = require('vue');

var app = new Vue({
	el: 'body#mainApp',

	data: {
		currentView: 'loading-view',
		app: {},
		viewData: {
			'edit-view': {
				ready: false,
				funcs_to_call: [],
				model: {}
			},
			'analytics-view': {
				ready: false,
				funcs_to_call: [],
				model: {}
			}
		}
	},

	components: {
	    // Views
		'analytics-view': require('./views/analytics'),
		'edit-view': require('./views/edit'),
		
		// Components
		'piece': require('./components/Piece')
	},

	methods: {
		call: function(view, name) {
			if(this.viewData[view].ready == true) {
				this.viewData[view].model[name]();
			} else {
				this.viewData[view].funcs_to_call.push(name);
			}
		}	
	},

	ready: function() {
	this.app = this;
		
        this.app.call('analytics-view', 'al'); //Test caling the al function
	}
});

module.exports = {
    data: function() {
        return {
            external: {}
        };
    },

    props: [
        'app'
    ],

    template: require('./analytics.template.html'),

    ready: function() {
        var view = 'analytics-view';
        this.app.viewData[view].ready = true;
        this.app.viewData[view].model = this;

        var methods = this.app.viewData[view].funcs_to_call;
        for(var i in methods)
        {
            this[methods[i]]();
        }
    },

    methods: {
        al: function() {
            alert('i got called!');
        }
    }
};

You can use these two files as templates when using this design architecture in the future! I know I will.

To the left is the file structure I have for the Laravue repo. There are a couple of differences though: 1) I have a home view not an analytics view, and 2) I use coffeescript instead of vanilla JS. These aren’t biggies though!

What now?

In the future, I’ll no doubt be optimizing this and making it better. If you have any suggestions, just leave a response below! Your input is essential because the only way this can thrive is through community involvement.

There’s a few important things missing from basic Vue and Laravel integrations.
In the future I may make a way to combine the ready and model variables in viewData functionally into one. But the additional code required may be more than I actually save, so I’m not sure on this one.

Something else I feel like this needs is a CLI. How about maybe php artisan make:view analytics and it will add all this boilerplate? Just an idea. Let me know if you’re interested in doing anything like this, because I think might be a bit beyond me.

For more info on how calling functions on objects using a string check out http://stackoverflow.com/questions/9854995/javascript-dynamically-invoke-object-method-from-string . It helped me out allot.

UPDATE: allow for arguments passed into view methods!

// app.js call method.
call: function(view, name, args = []) {
	if(this.viewData[view].ready == true) {
		this.viewData[view].model[name](args);
	} else {
		this.viewData[view].funcs_to_call.push({name: name, args: args});
	}
}

// updated for loop inside each view
for(var i in methods)
{
    this[methods[i].name](methods[i].args);
}

Now you can do this.app.call(‘foo’, ‘bar’, [‘arg1’, ‘arg2’, ‘arg3’]) and it will pass the array into the method. To retrieve them in a method just do args[0], args[1], args[2].

If you’re using coffeescript, it’s even easier! You can just use the … syntax for arguments. Yes, it’s technically possible without coffee, but it would look pretty ugly… Anyways here’s the coffeescript example:

call: (view, funcName, args...) ->
	if   @views[view].ready then @views[view]['model'][funcName].apply(null, args)
	else @views[view].funcs.push({name: funcName, args: args}) 

Any input is highly welcome!

30s ad

Vue JS 2 - The Complete Guide (incl. Vue Router & Vuex)

Build A Web App with VueJS, Spring Framework and MongoDB

Vue JS 2.0 - Mastering Web Apps

Vue JS 2: From Beginner to Professional (includes Vuex)

The Ultimate Vue JS 2 Developers Course

10 Best Vue Icon Component For Your Vue.js App

10 Best Vue Icon Component For Your Vue.js App

In this article, I will collect 10 Vue icon component to bring more interactivity, better UI design to your Vue application.

Icons are the vital element of the user interface of the product enabling successful and effective interaction with it. In this article, I will collect 10 Vue icon component to bring more interactivity, better UI design to your Vue application.

1. Animated SweetAlert Icons for Vue

A clean and simple Vue wrapper for SweetAlert's fantastic status icons. This wrapper is intended for users who are interested in just the icons. For the standard SweetAlert modal with all of its bells and whistles, you should probably use Vue-SweetAlert 2

Demo: https://vue-sweetalert-icons.netlify.com/

Download: https://github.com/JorgenVatle/vue-sweetalert-icons/archive/master.zip

2. vue-svg-transition

Create 2-state, SVG-powered animated icons.

Demo: https://codesandbox.io/s/6v20q76xwr

Download: https://github.com/kai-oswald/vue-svg-transition/archive/master.zip

3. Vue-Awesome

Awesome SVG icon component for Vue.js, with built-in Font Awesome icons.

Demo: https://justineo.github.io/vue-awesome/demo/

Download: https://github.com/Justineo/vue-awesome/archive/master.zip

4. vue-transitioning-result-icon

Transitioning Result Icon for Vue.js

A scalable result icon (SVG) that transitions the state change, that is the SVG shape change is transitioned as well as the color. Demonstration can be found here.

A transitioning (color and SVG) result icon (error or success) for Vue.

Demo: https://transitioning-result-icon.dexmo-hq.com/

Download: https://github.com/dexmo007/vue-transitioning-result-icon/archive/master.zip

5. vue-zondicons

Easily add Zondicon icons to your vue web project.

Demo: http://www.zondicons.com/icons.html

Download: https://github.com/TerryMooreII/vue-zondicons/archive/master.zip

6. vicon

Vicon is an simple iconfont componenet for vue.

iconfont
iconfont is a Vector Icon Management & Communication Platform made by Alimama MUX.

Download: https://github.com/Lt0/vicon/archive/master.zip

7. vue-svgicon

A tool to create svg icon components. (vue 2.x)

Demo: https://mmf-fe.github.io/vue-svgicon/v3/

Download: https://github.com/MMF-FE/vue-svgicon/archive/master.zip

8. vue-material-design-icons

This library is a collection of Vue single-file components to render Material Design Icons, sourced from the MaterialDesign project. It also includes some CSS that helps make the scaling of the icons a little easier.

Demo: https://gitlab.com/robcresswell/vue-material-design-icons

Download: https://gitlab.com/robcresswell/vue-material-design-icons/tree/master

9. vue-ionicons

Vue Icon Set Components from Ionic Team

Design Icons, sourced from the Ionicons project.

Demo: https://mazipan.github.io/vue-ionicons/

Download: https://github.com/mazipan/vue-ionicons/archive/master.zip

10. vue-ico

Dead easy, Google Material Icons for Vue.

This package's aim is to get icons into your Vue.js project as quick as possible, at the cost of all the bells and whistles.

Demo: https://material.io/resources/icons/?style=baseline

Download: https://github.com/paulcollett/vue-ico/archive/master.zip

I hope you like them!

Collection of 10 Vue Markdown Component for Vue.js App in 2020

Collection of 10 Vue Markdown Component for Vue.js App in 2020

Markdown is a way to style text on the web. The 10 Vue markdown components below will give you a clear view.

Markdown is a way to style text on the web. You control the display of the document; formatting words as bold or italic, adding images, and creating lists are just a few of the things we can do with Markdown.

The 10 Vue markdown components below will give you a clear view.

1. Vue Showdown

Use showdown as a Vue component.

View Demo

Download Source

2. showdown-markdown-editor

A markdown editor using codemirror and previewer using showdown for Vue.js.

View Demo

Download Source

3. markdown-it-vue

The vue lib for markdown-it.

View Demo

Download Source

4. perfect-markdown

perfect-markdown is a markdown editor based on Vue & markdown-it. The core is inspired by the implementation of mavonEditor, so perfect-markdown has almost all of the functions of mavonEditor. What's more, perfect-markdown also extends some features based on mavonEditor.

View Demo

Download Source

5. v-markdown-editor

Vue.js Markdown Editor component.

View Demo

Download Source

6. markdown-to-vue-loader

Markdown to Vue component loader for Webpack.

View Demo

Download Source

7. fo-markdown-note Component for Vue.js

fo-markdown-note is a Vue.js component that provides a simple Markdown editor that can be included in your Vue.js project.

fo-markdown-note is a thin Vue.js wrapper around the SimpleMDE Markdown editor JavaScript control.

View Demo

Download Source

8. Vue-SimpleMDE

Markdown Editor component for Vue.js. Support both vue1.0 & vue2.0

View Demo

Download Source

9. mavonEditor

A nice vue.js markdown editor. Support WYSIWYG editing mode, reading mode and so on.

View Demo

Download Source

10. vue-markdown

A Powerful and Highspeed Markdown Parser for Vue.

View Demo

Download Source

Thank for read!

Collection of 15 Vue Input Component for Your Vue.js App

Collection of 15 Vue Input Component for Your Vue.js App

Vue input component gives you a baseline to create your own custom inputs. It consists of a prepend/append slot, messages, and a default slot. In this article I will share 15 Vue input components to you.

Vue input component gives you a baseline to create your own custom inputs. It consists of a prepend/append slot, messages, and a default slot. In this article I will share 15 Vue input components to you.

1. Maska
  • No dependencies
  • Small size (~2 Kb gziped)
  • Ability to define custom tokens
  • Supports repeat symbols and dynamic masks
  • Works on any input (custom or native)

Demo

Download


2. v-range-flyout

A vue component that wraps a input type=number with a customizable range slider flyout with 2-way binding.

Demo

Download


3. vue-tel-input

International Telephone Input with Vue.

Demo

Download


4. Restricted Input

Allow restricted character sets in input elements.

Features

  • Disallow arbitrary characters based on patterns
  • Maintains caret position
  • Format/Update on paste
  • Works in IE11+

Demo

Download


5. Vue Currency Input

The Vue Currency Input plugin allows an easy input of currency formatted numbers.

Demo

Download


6. vue-fields

Input components for vue.js.

Demo

Download


7. vue-material-input

Simple example of issue I am seeing with input labels.

Demo

Download


8. vue-tribute

A Vue.js wrapper for Zurb's Tribute library for native @mentions.

Demo

Download


9. vue-number-smarty

Number input with rich functionality for Vue.js.

Features

  • integer/float
  • signed/unsigned
  • step size
  • increment/decrement value by scrolling when focused
  • align variants
  • min and max boundaries
  • max length of integer part (only for float type)
  • max length of float part (only for float type)
  • max length of string
  • error state
  • readonly state
  • theme options

Demo

Download


10. Vue input mask

Super tiny input mask library for vue.js based on PureMask.js (~2kb) exposed as directive. No dependencies.

Demo

Download


11. vue-r-mask

mask directive for vue.js

  • Template similar to javascript regular expression. /\d{2}/
  • Directive useful for your own input or textarea.
  • Arbitrary number of digits in template /\d{1,10}/

Demo

Download


12. Vue IP

An ip address input with port and material design support.

Demo

Download


13. v-money Mask for Vue.js

Tiny input/directive mask for currency

Features

  • Lightweight (<2KB gzipped)
  • Dependency free
  • Mobile support
  • Component or Directive flavors
  • Accept copy/paste
  • Editable

Demo

Download


14. Vue Masked Input

Dead simple masked input component for Vue.js 2.X. Based on inputmask-core.

Demo

Download


15. VueJS input component

Mobile & Desktop friendly VueJS input component
Features used
CSS variables
Vue's transition-group
Flexbox

Demo


I hope you like them!