PUG Template: Ignore undefined/null variables - express

I have an Expressjs application which uses PUG as view template compiler. I am on a registration form page.
I have the following code:
<div class="input-field">
<input type="email" name="email" id="email" value="!{req.email}">
<label for="email">Email address</label>
</div>
When browsing the route which renders the file, script crashes under the following error:
Cannot read property 'email' of undefined
Though I know req.email is undefined, I need it there to render the email address in case user inputs it and sends it through the form. How to ignore the error and keep the script execution going?

You could use a ternary conditional to check if the req object exists and has an email property, and if not, render an empty value attribute:
input#email(
type='email',
name='email',
value= (req && req.email) ? req.email : ''
)

Related

Scaffolded Identity Razor Pages Forms don't submit unless there is a route parameter

This happens on all the Scaffolded Identity Razor Pages that do not include a route parameter in the Form definition, but let's take the ForgotPassword one as an example:
Here is the form as defined on the scaffolded page:
<form method="post">
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="Input.Email"></label>
<input asp-for="Input.Email" class="form-control" />
<span asp-validation-for="Input.Email" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
When I click the submit button, nothing happens. The browser dev tools confirm nothing happens. The page does not submit to the server. (and yes, I have entered a valid email address; if I don't, then the jquery validation correctly displays the appropriate error messages.)
But I've found that if I change the form definition to include a route parameter, as follows:
<form asp-route-unusedArg="SomeValue" method="post">
then the submit button works fine, and the form is submitted to the server. (Even though the OnPostAsync method defined by the server code does not expect a parameter at all; it is defined as public async Task<IActionResult> OnPostAsync()). The way I figured this out was to compare the form definition with that of the Login form, which was working fine, and had a route parameter for returnUrl.
What is going on here? Why is the form not submitting unless I add a route parameter?

Pass UTC offset into controller route

Fairly new to ASP.NET CORE, come from WPF background.
Having some trouble understanding how to pass local variables around.
I have a form:
<span id="clock"></span>
<form asp-action="Create" asp-controller="Session" method="post" asp-route-session="#Model.Session">
<input asp-for="#Model.Session.ClientId" class="form-control" style="display: none" />
<ejs-dropdownlist id="clinics" dataSource="#Model.LinkableClinics" placeholder="Select Clinic" popupHeight="220px" ejs-for="#Model.Session.ClinicId">
<e-dropdownlist-fields text="Name" value="ClinicId"></e-dropdownlist-fields>
</ejs-dropdownlist>
<ejs-dropdownlist id="employees" dataSource="#Model.LinkableEmployees" placeholder="Select Employee" popupHeight="220px" ejs-for="#Model.Session.EmployeeId">
<e-dropdownlist-fields text="Name" value="EmployeeId"></e-dropdownlist-fields>
</ejs-dropdownlist>
<ejs-datetimepicker id="startdatetimepicker" placeholder="Select a date and time" ejs-for="#Model.Session.StartTime"></ejs-datetimepicker>
<ejs-datetimepicker id="enddatetimepicker" placeholder="Select a date and time" ejs-for="#Model.Session.EndTime"></ejs-datetimepicker>
<div class="form-group">
<input type="submit" value="Create Session" class="btn btn-primary" />
</div>
</form>
and I would like to add asp-route-offset to my form but I can't figure out how to pass a locally calculated variable into this routing.
This is a post, so I can't just use Url.Redirect() custom url builder.
I've also tried to add a hidden field and run a calculation inside the "value"
<input asp-for="#Model.Session.Offset" class="form-control" style="display: none" value="getValue()"/>
I'm calculating my offset in my <script> section as follows:
<script type="text/javascript">
window.onload = loaded;
function loaded() {
var clockElement = document.getElementById("clock");
function updateClock(clock) {
clock.innerHTML = new Date().getTimezoneOffset() / 60;
}
}
</script>
I've tried setting variables or the #Model object here, but nothing seems to want to stick.
Anyone have experience trying to pass a variable like this? Or a better way to pass UTC offset into my timestamp?
You're trying to mix and match things happening server-side and client-side. Your script which gets the offset runs client-side, after the server has sent the response. Your Razor code runs server-side, before the client has even received the page.
Long and short, if you want to update the value, you have to do it via client-side means, namely JavaScript:
document.getElementById('#Session_Offset').value = new Date().getTimezoneOffset();
You can't use something like asp-route-offset at all, because the offset is coming from the client and can't be used to generate the post URL. As a result, you'll need to stick with the hidden input approach.

axios.post automatically splice url with my params

I want to implement an api with vue and axios in my front-end:
methods:{
startSpider:function(event){
alert("spider is ready to run!");
let data = {'searchKey':this.searchKey,
'category':this.category,
'num':this.num};
axios.post("{% url 'main:getCommodityInfo'%}",
data,
{headers:{'X-CSRFToken': this.getCookie('csrftoken')}})
.then(response=>{
console.log(response.data)
})
.catch(error=>{
console.log(error);
alert("connection has error")
})
},
When I call this function, I expect to get data from the back-end and stay at the inital url. It does receive data but the url quickly changed.
After some exploration, I find the browser implement two request! First, POST, and next GET:
Using 'searchKey':'switch', 'category':'electronic','num':60 as an example.
and My browser url subsequently changes to
Why it happens? I have just used POST not GET. The axios post seems to automatically splice inital url with the params. I have tried a lot of ways but failed. Even I have writed a small demo with the similiar structure like this to test, but the demo runs well! What happened? Help me please...
Updated I: Give my server behavior(django-view) and my router related is path('getCommodityInfo/',views.getCommodityInfo, name = 'getCommodityInfo')
def getCommodityInfo(request):
print(request.body)
return JsonResponse({"data":True}, safe=False)
Updated II: Give my front-end form:
<form>
<label for="searchKey">KeyWords</label>
<input v-model="searchKey" placeholder="Input Search Key" type="string" class="form-control" id="searchKey" name="searchKey">
<label for="category">Commodity Category</label>
<select v-model="selected" id="category" name="category">
<option v-for="option in options" v-bind:value="option.value">
${option.text}
</option>
</select>
<br>
<label for="num">Amount</label>
<input v-model="num" placeholder="Input amount needed" type="string" class="form-control" id="num" name="num" >
<button v-on:click="startSpider" class="btn btn-default">Submit</button>
<p>KeyWords : ${ searchKey }</p>
<p>Category : ${ selected }</p>
<p>Amount: ${ num }</p>
</form>
The bug happened because of not setting button type.
We could check this:
The missing value default is the Submit Button state.
And in the front-end form there is no type for the button, so the button type will be submmit button. When click on the button, it will automatically send a get request.
Modify the button like this:
<button v-on:click="startSpider" class="btn btn-default" type='button'>Submit</button>

vee-validate validation message not working in Laravel 5.6.7

I am using Laravel 5.6.7 with vue.js for form validation. I have successfully installed using npm install vee-validate#next --save
<form role="form">
<select name="Role_ID" v-validate data-vv-rules="required">
<option :value="-1" selected>Please select Role</option>
<option v-for="RoleRecord in RoleRecords" :value="RoleRecord.Role_ID">
{{RoleRecord.Role}}
</option>
</select>
<p v-if="errors.has('Role_ID')">{{ errors.first('Role_ID') }}</p>
<!-- UserName -->
<div>
<label>UserName</label>
<div class="col-md-9">
<input name="User Name" v-validate data-vv-rules="required" type="text"
v-model="createForm.UserName">
<p v-if="errors.has('User Name')">{{ errors.first('User Name') }}</p>
</div>
</div>
<button type="button" #click="validateBeforeSubmit()">
Save Changes
</button>
</form>
<script>
export default {
methods: {
validateBeforeSubmit() {
this.$validator.validateAll();
}
}
}
</script>
My findings
Due to some reasons the option is not being validated.
There is UserName field which is working perfectly.
I am expecting that it should show the error message if the option selected value is less then 0
Am I missing anything? Please let me know if you need more info.
in the vee-validate doc,
The field under validation must have a non-empty value. By default,
all validators pass the validation if they have "empty values" unless
they are required. Those empty values are: empty strings, undefined,
null.
-1 is still considered a valid value for required validation. Use specified empty values instead. (Namely: empty strings, undefined, null)
e.g.
<option :value="null" selected>Please select Role</option>
This should trigger the required validation.
Example: https://codepen.io/jacobgoh101/pen/geaqwr?editors=1011
There's a difference between your naming:
<input name="User Name" v-validate data-vv-rules="required" type="text" v-model="createForm.UserName">
<p v-if="errors.has('User Name')">{{ errors.first('User Name') }}</p>
v-model uses UserName (without spacing). The name-attribute in your input and errors.has + errors.first are using User Name (with spacing). Please make sure you're naming things exactly the same, both in front-end as well as in back-end (and preferably without whitespace).

Vue property not valid with underscore

I was doing some tests and I noticed that my properties are not valid when I used underscore.
Example:
new Vue({
el : "#form",
data: {
errors: [],
_username: '',
_password: ''
});
on html file:
<input class="uk-input" type="text" v-model="_username" >
<input class="uk-input" type="password" v-model="_password">
With the code above the app won't render. If I remove the underscore it will work, does someone knows why this happens?
The answer may be found in the documentation
Properties that start with _ or $ will not be proxied on the Vue instance because they may conflict with Vue’s internal properties and API methods. You will have to access them as vm.$data._property
In your templates, you will have to reference $data._username / $data._password, eg
<input class="uk-input" type="text" v-model="$data._username" >
<input class="uk-input" type="password" v-model="$data._password">
Demo here ~ https://jsfiddle.net/9bzxuecj/2/