I'm trying to set up a .NET core project using Razor Pages and include vueJs inside the razor page for all my logic.
Something like this:
#{
ViewData["Title"] = "VueJs With Razor";
}
<h2>#ViewData["Title"].</h2>
<div id="app">
<span>{{ message }}</span>
</div>
<script>
new Vue({
el: '#app',
data: {
message : 'Hello vue.js'
}
})
</script>
I have read that mixing Vue and Razor pages is a bad practice, and one should use Razor OR Vue.
Why is this?
Mixing VueJs and Razor Pages is not necessarily a bad thing, it can be great!
I use Vue with razor for non SPA pages and the two work well together. I choose to use Vue by loading it via a script tag from a CDN and and I do not leverage the use of WebPack for transpiling, I simply write my code in (gasp) ES5. I chose this approach for the following reasons.
Using Razor pages rather than a SPA aids in SEO and search engine ranking of public facing pages.
Loading Vue directly from a CDN eliminates a whole stack of Webpack centric technology from the learning curve which makes it much easier for new devs to get up to speed on the system.
The approach still provides the reactive goodness to UI development that Vue inherently brings to the table.
By keeping with the “page model” the code that delivers site functionality is logically grouped around the backend page that delivers that functionality.
Since Vue and Razor can do many of the same things, my goal for public facing pages is to use Razor to generate as close to the final html as possible, and to use Vue to add the reactiveness to the page. This delivers great SEO benefits for crawlers that index the page by parsing the HTML returned.
I realize the my usage of Vue is quite different than going the route of a SPA and WebPack and the approach often means I can't use 3rd party Vue Components without reworking the code a bit. But the approach simplifies the software architecture and delivers a lightweight reactive UI.
By using this approach Razor can be heavily leveraged to generate the initial rendering of the HTML with some tags containing vue attributes. Then after the page loads in the browser, Vue takes over and can reconfigure that page any way desired.
Obviously, this approach will not fit the needs of all developers or projects but for some use cases it's quite a nice setup.
A few more details for those interested
Since I use vue sitewide, my global _layout.aspx file is responsible for instantiating vue. Any sitewide functionality implemented in vue is implemented at this level. Many pages have page specific vue functionality, this is implemented as a mixin on that page or a mixin in a js file loaded by that page. When the _layout.aspx page instantiates Vue it does so with all the mixins that I have registered to a global mixin array. (The page pushed it's mixin on that global mixin array)
I don’t use .vue files. Any needed components are implemented either directly on the page or if they need to be used by multiple pages then they are implemented in a partial view like the one below.:
dlogViewComponent.cshtml :
#* dlog vue component template*#
<script type="text/x-template" id="dlogTemplate">
<div class="dlog" v-show="dlog.visible" v-on:click="dlog.closeBoxVisible ? close() : ''">
<div class="dlogCell">
<div class="dlogFrame" ##click.stop="" style="max-width:400px">
<i class="icon icon-close-thin-custom dlogCloseIcon" v-if="dlog.closeBoxVisible" ##click="close()"></i>
<div class="dlogCloseIconSpace" v-if="dlog.closeBoxVisible"></div>
<div class="dlogInner">
<div class="dlogTitle" style="float:left" v-text="title"></div>
<div class="clear"></div>
<div class="dlogContent">
<slot></slot>
</div>
</div>
</div>
</div>
</div>
</script>
#* Vue dlog component *#
<script type="text/javascript">
Vue.component('dlog', {
template: '#dlogTemplate',
props: { //don't mutate these!
closeBoxVisible: true,
title: 'One'
},
data: function () {
return {
dlog: { //nest the data props below dlog so I can use same names as cooresponding prop
closeBoxVisible: (typeof this.closeBoxVisible === 'undefined') ? true : (this.closeBoxVisible == 'true'),
title: (typeof this.title === 'undefined') ? '' : this.title,
visible: false
}
}
},
methods: {
//opens the dialog
open: function () {
app.hideBusy(); //just in case, no harm if not busy
this.dlog.visible = true;
var identifyingClass = this.getIdentifyingClass();
Vue.nextTick(function () {
$("." + identifyingClass).addClass("animateIn");
fx.manageDlogOnly();
});
},
//closes the dialog
close: function () {
fx.prepDlogClose();
var identifyingClass = this.getIdentifyingClass();
this.dlog.visible = false;
$("." + identifyingClass).removeClass("animateIn");
},
getIdentifyingClass: function () {
if (this.$el.classList.length > 1) {
//the last class is always our identifying css class.
return this.$el.classList[this.$el.classList.length - 1];
} else {
throw "A dialog must have an identifying class assigned to it.";
}
}
}
});
</script>
In the above, it's the Vue.component('dlog', ... part of the js that installs the component and makes it available to the page.
The vue code on the _layout.cshtml page looks something like the code below. By instantiating Vue on the _layout.cshtml which is used by the whole site, Vue is only instantiated in a single place sitewide:
_layout.cshtml :
<script type="text/javascript">
var app = new Vue({
el: '#appTemplate',
mixins: mixinArray, //The page adds it's mixin to mixinArray before this part of the layout executes.
data: {
errorMsg: '' //used sitewide for error messages
//other data used sitewide
},
methods: {
//methods that need to be available in vue sitewide, examples below:
showBusy: function (html) {
//functionality to show the user that the site is busy with an ajax request.
},
hideBusy: function () {
//functionality to hide the busy spinner and messaging
}
},
created: function () {
//this method is particularly useful for initializing data.
}
});
</script>
What I have provided here paints a pretty clear picture of this non-traditional approach and it's benefits. However, since several people asked, I also wrote a related blog post: Using VueJs with ASP.NET Razor Can Be Great!
You can do this. Sometimes you're obliged to do it, if, like us, you're migrating an existing code base and you can't convert everything at once. And as Ron C says, it works well.
If you're starting a new project, you have the luxury of choosing. Reasons for favouring an SPA and no Razor would be...
Reactivity. SPA apps generally feel (much) more reactive. Initial renders are often served from cache, before the data arrives. On first load, all resources arrive in a bundle, in one request-response. There's no, or much less, request chaining.
Workflow. Webpack, bundling and hot reloads are great. You get production builds, with minification, compilation of Vue render functions, elimination of 404 style errors, js syntax errors are trapped. The cycle from introducing an error to discovering it is greatly reduced for many errors.
SPA universe. Routing, Vuex, this really is the way of the future.
Purity. Razor and Vue do similar things at the end of the day. If you mix them, you may have a hard time keeping your head straight.
You can now also lint the VueJS templates within the Razor views:
https://www.npmjs.com/package/razor-vue-lint
Great answers and content on this question! Just to add re the OP, the official Vue documentation expressly states that you can mix and match and do what you like with Vue and that it is designed to be used incrementally so I'd say if it fits what you're trying to do then it is NOT an automatic bad practice.
Situation:
I'm using React in a Meteor app.
My packages for authentication: accounts-password; useraccounts:core
I also use the gadicc:blaze-react-component to render the {{> atForm }} template in my react component =><Blaze template="atForm" />
Problem:
I don't know what should be the proper syntax to secure a specific page as described in the useraccounts guide but with react.
Lets suppose that I want to secure <Mypage /> imported from './mypage.jsx'
How can I call {{> ensureSignedIn template="myTemplate"}} and reaplace "myTemplate" by <Mypage /> ?
I tried <Blaze template="atForm" template={Mypage} /> without success...
Is it even possible to make something like this ?
You can check Meteor.userId() in ComponentWillMount(), set state and check it in render(). Or use some kind of checkings in your router
I found a solution:
With kadira:flow-router Meteor's package, using react-layout and useraccounts:flow-routing, I can do something like that:
FlowRouter.route('/private', {
triggersEnter: [AccountsTemplates.ensureSignedIn],
action: function() {
ReactLayout.render(Mypage, {myprops: myprops.value});
}
});
It seems that it all happens into triggersEnter: [...] key.
More details here.
I've got an legacy Umbraco ASP.NET site (v4.7) which I've been requested to place a SalesForce web to sales form on it. I've done this and all is well apart from the amount of spam that's getting through.
So I'm trying to use the Google NoCaptcha widget which I've successfully placed on the form but I don't know how to validate the response. All of the examples I've searched are using PHP cURL method which I cannot use.
To further complicate things the site is compiled and I've don't have access to the source files so I can't create any controls/classes, etc. in the solution.
Is it possible to validate the recaptcha response using only the 'client' (javascript for example) with no back end processing done?
Any help would be greatly appreciated.
Thanks,
Craig
set the enabled property of the button to false.
<asp:button id="btnName" enabled="false" text="submit" />
and then on the recaptcha container:
<div id="asd" class="g-recaptcha" data-callback="EnableButton" data-expired-callback="DisableButton" data-sitekey="your-site-key">
</div>
where data-callback and data-expired-callback are events of the widget.
data-callback:
invoked after a successful captcha
data-expired-callback:
invoked when session times out.
where EnableButton and DisableButton are javascript functions which does exactly what they say they do.
<script type="text/javascript">
var DisableButton = function () {
alert("Confirmation Expired. Please Answer Recaptcha.");
document.getElementById('<%=btnName.ClientID %>').disabled = true;
grecaptcha.reset();
};
var EnableButton = function () {
document.getElementById('<%=btnName.ClientID %>').disabled = false;
};
</script>
but it is really recommended to still verify it on server-side.
hope it helps..
I am new to meteor.. I am looking for a way to perform 2 way databinding between a model/collection to template. It is my understanding that when the contents of a collection change, the template reacts to this change and updates itself. However, how to automatically the collection when a user types, for example, in a textbox?
You could use the template events binding
e.g if you have
html
<template name="home">
<input type="text" name="text" value="{{text}}"/>
</template>
client js
Template.home.text = function() {
return MyCollection.findOne({_id:"1"}).text;
}
Template.home.events({
'change input[name=text]':function(event,context) {
MyCollection.update(_id, {$set:{text:event.target.value}});
}
});
So that will make it update as soon as the textbox loses focus/enter is pressed/etc
If you want to use the submit button & for something a bit cooler have a look at the controllers branch of meteor on github for the
easy forms system currently in the works to easen this up a bit.
I have an application on facebook and i have the facebook comment box on it. If someone makes a comment using the comment box, is there a way to notify person that a post has been made on their app
I have the following code
<script src="https://connect.facebook.net/en_US/all.js#xfbml=1"></script>
<fb:comments xid="test" canpost="true" candelete="false" href="<%= link %>" num_posts="10" width="500" send_notification_uid="<%= fbUserId %>" notify="true" publish_feed="true"></fb:comments>
The href - link is a dynamic link depending on where the post was made. The send_notification_uid - user_Id is also dynamic and it retrieves the user id of the person that owns the page.
Any help would be great. It all works apart from the send notification
I believe using the javascript SDK you can subscribe to the comment.create event. Then provided you have the necessary permissions for the uid in question, you could then send them a notification I believe. I haven't tested this but you need to look at the FB.event.subscribe code
https://developers.facebook.com/docs/reference/javascript/FB.Event.subscribe/
There's some more information on a post here
http://facebook.stackoverflow.com/questions/6146925/fb-event-subscribecomment-create-doesnt-work
Further to this you can test things out on the js skd tool
https://developers.facebook.com/tools/console/
and some sample code
<h1>Defaults</h1>
<fb:comments href="http://www.fbrell.com/"></fb:comments>
<script>
FB.Event.subscribe('comments.add', function(resp) {
console.log('Comment was added' + resp);
});
</script>
I don't know if the specs changed, but the current answer doesn't work anymore, the new way is now this :
FB.Event.subscribe('comment.create', function() {
console.log('Comment was added');
console.log(arguments);
});
comment.create , as explained here : https://developers.facebook.com/docs/reference/javascript/FB.Event.subscribe/v2.0#comments-example