OctoberCMS frontend image upload - file-upload

I'm trying to upload profile phoho in front end of OctoberCMS but with no luck.
Cannot catch it in the backend to save within the user.
Made everything exactly like in documentation of the CMS.
Need to make this work without any eternal plugins.
<form data-request="onCreateUser" data-request-update="user:'.res_user'" >
<input name="file_input" type="file" >
<button type="submit" class="subBtn">Create User</button>
</form>
In User i have:
public $attachOne = [
'avatar' => 'System\Models\File'
];
and this code:
$file = new System\Models\File;
$file->data = Input::file('file_input');
$file->is_public = true;
$file->save();
$model->avatar()->add($file);
Record stored in DB, but its empty. filesize = 0
Can anyone please help me with this?
Asked the big Bro, but found that this problem is very common, and have no solution.
Thanks
Update:
This is working, when I use this:
{{ form_open({files: true, request: 'onCreateConcert'}) }}
<!--File Input-->
<input type="file" name="file-upload" required="required">
<!--File Input-->
<!--Submit/Upload Button-->
<button type="submit">Upload</button>
{{ form_close() }}
but not with my form. whats i'm missing here?
I added as well token and session_key
{{ form_sessionKey() }}
{{ form_token() }}

It because you don't add enctype="multipart/form-data" to your form attribute.
When you use twig like {{ form_open({files: true, request: 'onCreateConcert'}) }}, the files: true will add attribute to your form to handle upload file. So the twig above will generate tag like below,
<form data-request="onCreateConcert" enctype="multipart/form-data">

try this:
use System\Models\File;
use Input;
[...]
if (Input::file("file_input")) {
$model->avatar = Input::file("file_input");
}
model->save();

Related

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>

Shopify PLUS - additional checkout custom field

I was trying to add additional custom field in the checkout screen and here is my code:
<div class="additional-checkout-fields" style="display:none">
<div class="fieldset fieldset--address-type" data-additional-fields>
<div class="field field--optional field--address-type">
<h2 class="additional-field-title">ADDRESS TYPE</h2>
<div class="field__input-wrapper">
<label>
<input data-backup="Residential" class="input-checkbox" aria-labelledby="error-for-address_type" type="checkbox" name="checkout[Residential]" id="checkout_attributes_Residential" value="Residential" />
<span>Residential</span>
</label>
<label>
<input data-backup="Commercial" class="input-checkbox" aria-labelledby="error-for-address_type" type="checkbox" name="checkout[Commercial]" id="checkout_attributes_Commercial" value="Commercial" />
<span>Commercial</span>
</label>
</div>
</div>
</div>
</div>
<script type="text/javascript">
if (window.jQuery) {
jquery = window.jQuery;
} else if (window.Checkout && window.Checkout.$) {
jquery = window.Checkout.$;
}
jquery(function() {
if (jquery('.section--shipping-address .section__content').length) {
var addType = jquery('.additional-checkout-fields').html();
jquery('.section--shipping-address .section__content').append(addType);
}
});
</script>
It returns the checkout page like this -
The problem is - once I click continue button and comes back to this page again, I don't see the checkbox checked. I feel the values are not being passed or may be something else.
What am I missing?
From the usecase, it looks like you want the user to select the Address Type either Residential or Commercial so a raido button group seems more suitable. I have edited the HTML to create the Radio Button instead of Checkbox. To maintain the state, I have used Session Storage. You may also replace Session Storage with Local Storage if you want to do so. For explanation check code comments.
<div class="additional-checkout-fields" style="display:none">
<div class="fieldset fieldset--address-type" data-additional-fields>
<div class="field field--optional field--address-type">
<h2 class="additional-field-title">ADDRESS TYPE</h2>
<div class="field__input-wrapper">
<label>
<input class="input-radio" aria-label="" type="radio" name="checkout[address_type]" id="checkout_attributes_Residential" value="residential" checked>
<span>Residential</span>
</label>
<label>
<input class="input-radio" aria-label="" type="radio"name="checkout[address_type]" id="checkout_attributes_Commercial" value="commercial">
<span>Commercial</span>
</label>
</div>
</div>
</div>
</div>
JavaScript part
<script type = "text/javascript" >
if (window.jQuery) {
jquery = window.jQuery;
} else if (window.Checkout && window.Checkout.$) {
jquery = window.Checkout.$;
}
jquery(function() {
if (jquery('.section--shipping-address .section__content').length) {
var addType = jquery('.additional-checkout-fields').html();
jquery('.section--shipping-address .section__content').append(addType);
// Get saved data from sessionStorage
let savedAddressType = sessionStorage.getItem('address_type');
// if some value exist in sessionStorage
if (savedAddressType !== null) {
jquery('input[name="checkout[address_type]"][value=' + savedAddressType + ']').prop("checked", true);
}
// Listen to change event on radio button
jquery('input[name="checkout[address_type]"]').change(function() {
if (this.value !== savedAddressType) {
savedAddressType = this.value;
sessionStorage.setItem('address_type', savedAddressType);
}
});
}
});
</script>
You are responsible for managing the state of your added elements. Shopify could care a less about stuff you add, so of course when you flip around between screens, it will be up to you to manage the contents. Use localStorage or a cookie. Works wonders. As a bonus exercise, ensure that your custom field values are assigned to the order when you finish a checkout. You might find all your hard work is for nothing as those value languish in la-la land unless you explicitly add them as order notes or attributes.

Using vee-validate for validation of dropbox

Sorry for the very basic question
I'm trying to validate a form using vee-validate. text/email/number fields are not a problem. But I couldn't find a good documentation on validating dropdown/checkbox/radio fields.
What I want is "you have to select some option from the dropdown". For that i tried
<p class="help is-danger" v-show="standard===''">Select the standard student is studing in.</p>
where standard is the property which is binded with the help of v-model="standard". This is working as intended, but i want this message to be shown when dropdown is "touched". I'm not able to figure this out.
You can use the data-vv-validate-on attribute:
data-vv-validate-on="focus"
Then whenever the dropdown is opened the validator will fire, for instance.
I found a workaround for this,
<div class="select" :class="{'is-success': standard!='', 'is-danger': standard=='' && standardIsFocused}">
<select v-model="standard" #focus.once="standardToggle()">
...
</select>
</div>
<p class="help has-text-left is-danger" v-show="standard==='' && standardIsFocused">Selecting one of the option is required.</p>
in script tags
data () {
return {
standardIsFocused: false,
},
methods: {
standardToggle() {
this.standardIsFocused = !this.standardIsFocused
}
}

jekyll passing variable to form page

I try to find a way to create a single booking form with jekyll.
I got for instance a button for booking at my tour details page.
When user click that button, I would love to know if there's a way to pass parameters to the booking page in order to display for example the name -- prices -- etc... of the tour.
I can't figure out how or even if its possible. Anyone clever enough for pointing me the right direction( if there's one) ?
Yes, it's possible, but as Jekyll is static, you have to do this on client side.
Explanation.
The tour page (tour.html):
---
title: tours
layout: page
tour:
name: Flying with eagles
description: text here
price: 120€
---
{% capture url %}n={{ page.tour.name | uri_escape }}&p={{ page.tour.price | uri_escape }}{% endcapture %}
<h2>{{ page.tour.name }} ({{ page.tour.price }}) - Book me for this tour!</h2>
<p>{{ page.tour.description }}</p>
Note that we use page variables to store values like name and price, but you can hard code this in the page body:
<h2>{{ page.tour.name }} ({{ page.tour.price }}) - Book me for this tour!</h2>
then becomes :
<h2>Flying with eagles (120€) - Book me for this tour!</h2>
the form (tour_form.html) :
---
title: tour form
layout: page
---
<form accept-charset="UTF-8" action="" method="POST">
<input type="text" name="tourName" value="">
<input type="text" name="tourPrice" value="">
<input type="email" name="email" placeholder="Your Email">
<input type="text" name="name" placeholder="Your Name">
<button type="submit">Submit</button>
</form>
<script>
// this script will automatically fill name and price fields
// depending on what's passed in the url
var fillForm = function () {
var queryString = document.location.search.split("+").join(" ");
var params = {}, tokens, re = /[?&]?([^=]+)=([^&]*)/g;
while (tokens = re.exec(queryString)) {
params[decodeURIComponent(tokens[1])] = decodeURIComponent(tokens[2]);
}
if (params.n == undefined && params.p == undefined){
// no value in the query string
// here you have to manage this use case : redirect or print a message to user
}else{
// filling form fields with query string values
document.getElementsByName('tourName')[0].value = params.n;
document.getElementsByName('tourPrice')[0].value = params.p;
}
} ();
</script>
This form is automatically filled with parameters passed from tour.html.
It can then be pointed to a form service like http://forms.brace.io/, http://www.jotform.com/ or any form service to deliver submitted datas.
Note: some services need a callback page to redirect to when the form is submitted.
You then need to make another page (eg: thankyou.html) in witch you'll have to parse and present url passed datas to user.

sails js: add EJS template using jQuery

I am trying append EJS templates using jQuery, I am not sure if what I am doing is right.
views/form/room-form.ejs
<form>
...
<div class="add_room_inputs">
<%- include partials/add_room %>
</div>
<div id="NewAddRoomForm">
<p>Add new form</p>
</div>
...
</form>
\assets\linker\js\custom-functions.js
$(document).ready(function(){
$('#NewAddRoomForm').click(function() {
$('.add_room_inputs').append('<%- include /assets/linker/templates/add-room-input.ejs %>');
});
}
/assets/linker/templates/room-input.ejs
<input name="rooms[]" class="form-control" placeholder="Room Name" type="text">
alternative solution (custom-functions.js file) which fails on file not found
var html = new EJS({url: '/assets/linker/templates/add-room-input.ejs.ejs'}).render();
$('#NewAddRoomForm').click(function() {
$('.add_room_inputs').append(html);
});
How can I implement such thing?
Did you include jst.js in the layout? by default it should be there as you are using Sails JS.
What you're trying to do wont work...
The problem is that the server has already rendered the template and sent the result to the client. Also the client doesn't have access to the view files on the server.
An Ajax framework like KnockoutJS is probably closer to what you are looking for, but there are others.
Here...I decided to make you a fiddle
http://jsfiddle.net/8D34n/23/
SO wants code too so here is a repaste
<form>
<h1 data-bind="text: form_title"></h1>
Add Form
<br><br>
<div id="NewAddRoomForm" data-bind="foreach: form_list">
<div data-bind="text: 'Form '+($index() + 1)"></div>
<input data-bind="value: name" /><br>
<input data-bind="value: age" />
</div>
<br><br>
</form>
View results