Updating select box with Ajax, JavaScript and Webmatrix - sql

I'm very new to Ajax.
What I'm trying to achieve, I would imagine, is fairly common. I have 2 dropdown boxes, referencing my database, these are called "area" and "resort". The idea is that when i choose and area from the first boxes, it ONLY shows resorts within that area in the second box.
Here is my form:
<div id ="homepage-form-div" class="row">
<form id ="homepage-form"action=" /Search1.cshtml">
<div class="span3">
<label>Area:</label>
<select name="area">
<option value="">Any</option>
#foreach(var row in qlistarea){
<option value="">#row.AreaName</option>
}
</select>
</div>
<div class="span3">
<label>Resort:</label>
<select name="resort">
<option value="">Any</option>
#foreach(var row in qlistresort){
<option value="">#row.ResortName</option>
}
</select>
</div>
<button type="submit" class="btn btn-default" value="Submit" style="p">Go!</button>
</form>
</div>
I thought it might be useful to see my current SQL code:
var listarea = "SELECT DISTINCT AreaName FROM ResortInfo";
var qlistarea = db.Query(listarea);
var listresort = "SELECT DISTINCT ResortName FROM ResortInfo";
var qlistresort = db.Query(listresort);
I'm guessing I'll need to somehow add a "+ WHERE AreaName = something" to the second query, dependant on the result of the AJAX call right?

Ok, you are using Razor syntax? Lets the show begin. And hey, arent you the same guy?
First I will tell you the basics of what I use.
I use the click keyup or change events.
I update the content of the body on ajax calls.
You need some basic tutorials buddy! Learn ASP.NET, then Learn jQuery Ajax! That will be simple.
My humble request to you:
Buddy please atleast once search for the code, before pasting it here. You will get alot of downvotes and might get blocked for posting more questions here. Please search for questions first. However this is the code.
Ok, to create the code:
I am going to post the code that works for me. Ok?
Here is the main page content:
#{
Layout = "~/_SiteLayout.cshtml";
}
<script>
$(document).ready(function () {
$('#area').change(function () {
$.ajax({
url: "testtworesult",
data: "type=resortupdate&resval=" + $('#area').val(),
success: function (data) {
$('#resort').html(data);
}
});
});
$('.btn').click(function () {
$.ajax({
url: "testtworesult",
data: "type=submit&area=" + $('#area').val() + "&res=" +
$('#resort').val(),
success: function (data) {
$('#result').html(data);
}
});
});
});
</script>
<div id ="homepage-form-div" class="row">
<div class="span3">
<label>Area:</label>
<select id="area">
<option value="">Any</option>
<option value="1">One</option>
<option value="2">Two</option>
</select>
</div>
<div class="span3">
<label>Resort:</label>
<select id="resort">
<option value="">Any</option>
<option value="Love">Love</option>
<option value="Hate">Hate</option>
</select>
</div>
<button type="submit" class="btn btn-default" value="Submit" style="p">Go!</button>
<div style="font-weight: bold; margin-top: 20px;" id="result"></div>
</div>
Then the ajax page:
#{
var db = Database.Open("StayInFlorida");
var getresortval = Request.QueryString["resval"];
var type = Request.QueryString["type"];
var res = Request.QueryString["res"];
var area = Request.QueryString["area"];
var listresort = "SELECT DISTINCT ResortName FROM ResortInfo WHERE AreaName = '#0'";
var qlistresort = db.Query(listresort, getresortval);
if(type == "resortupdate") {
if(getresortval == "Kissimmee") {
Response.Write ("<option value='kissimmee'>Kissimmee</option");
}
if(getresortval == "Davenport") {
Response.Write("<option value='davenport'>Davenport</option");
}
} else if(type == "submit") {
Response.Write(#"You selected the Resort!<br>
Your area was: " + area + #".<br>
And your resort was: " + res + #". Hope you have a great trip!");
}
}
This won't save the content in Database, you will need to use INSERT INTO for that. Then you will require SELECT * FROM to select the data. I have simply used Response.Write().
Good luck.

For the AJAX call, you need a function AJAX can call which houses the Resort query after the user selects an Area. I'm not familiar with Razor or Webmatrix, so here's a pseudo-function (based on PHP) that you might be able to translate to your environment:
if (isset($_POST['area'])) set_resort(); /*AJAX will set $_POST['area'], then do function that returns output to AJAX*/
. . .
function set_resort() {
var listresort = "SELECT DISTINCT ResortName FROM ResortInfo WHERE AreaName = " $_POST['area']; /*make sure you escape that variable, however you do that in your syntax*/
var qlistresort = db.Query(listresort);
var resortArray = array(); /*or however you make arrays in your syntax*/
#foreach(var row in qlistresort){
resortArray[] = #row.ResortName; /*append each resort name to array*/
}
echo json_encode(#resortArray); /*JSON is preferred way to echo array back to AJAX*/
}
Your HTML would look like...
<div id ="homepage-form-div" class="row">
<form id ="homepage-form"action=" /Search1.cshtml">
<div class="span3">
<label>Area:</label>
<select id="areaSelect" name="area"> <!-- add an ID for easier jQuery selection -->
<option value="">Any</option>
#foreach(var row in qlistarea){
<option value="">#row.AreaName</option>
}
</select>
</div>
<div class="span3">
<label>Resort:</label>
<select id="resortSelect" name="resort"> <!-- add an ID for easier jQuery selection -->
<option value="">Any</option>
</select>
</div>
<button type="submit" class="btn btn-default" value="Submit" style="p">Go!</button>
</form>
</div>
Finally, your jQuery AJAX call would be like:
$('#areaSelect').on('change', function() {
var str = $(this).serialize();
$.ajax({
type: 'POST',
url: /*URL of your page*/
dataType: 'json',
data: str,
error: function(XMLHttpRequest, textStatus, errorThrown) {
console.log(errorThrown + '\n' + textStatus);
},
success: function(msg) {
$.each(msg, function(index, value) {
$('#resortSelect').append('<option value=' + index + '>' + value + '</option>'; /*add each resort from the set_resort() query to the resort select input*/
});
});
});

Related

How handle event like click in RazorPages by C# functions

I want to call a C# function when I click on a button, or select an item in selectList on the razor page.
In blazor , it is possible like this code:
<button class="btn btn-info form-control" #onclick="AddNewCategory" >Add New Category</button>
but in razor page, I can't use it
Please help me!
If you want to select an item in selectList on the razor page when clicking on a button,you can try to use js,here is a demo.When clicking the button,the selected value will be 4.
<select id="select1">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>
<button onclick="changeSelectedItem()">test</button>
#section Scripts{
<script>
function changeSelectedItem() {
$("#select1").val(4);
}
</script>
}
And if you want to call a C# function when I click on a button,you can use ajax to call a handler.here is a demo:
cshtml:
#Html.AntiForgeryToken()
<button onclick="callHandler()">callHandler</button>
#section Scripts{
<script>
function callHandler() {
$.ajax({
type: "POST",
url: "?handler=TestHandler",
headers: { "RequestVerificationToken": $('input[name="__RequestVerificationToken"]').val() },
success: function (data) {
//...
}
});
}
</script>
}
cshtml.cs:
public void OnPostTestHandler()
{
//do something here
}

Vue JS - Display option 2 of select menu after it is disabled

I am looking for help on how to display the second option in a select drop-down menu after the select menu is disabled.
It is disabled if there are fewer than 2 options left. The first option is the 'Please select' option but I would like it to display the one remaining option which is the second option. i.e. 'Scotland' in the code below. The data is pulled in using an Axios call so I do not know what the value will be.
Any help would be greatly appreciated.
The select menu code
<select disabled="disabled">
<option disabled="disabled" value="">Select nationality</option>
<option value="Scotland"> Scotland </option>
</select>
Vue
computed: {
selectDisabled: function() {
return this.options.length <= 2;
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<select v-model="quantity" :disabled="selectDisabled">
<option disabled value="">Select</option>
<option v-for="option in options" :value="option">{{option}}</option>
</select>
</div>
You need to create a special computed property that will dynamically tell the <select> which option it should show inside itself. <select> show the option that matches the <select>'s value.
So:
When the select is disabled (has less than 2 options) force it's value to be the value of the first listed option (this.options[0]).
When the select is enabled, pass the normal value selected by the user (this.value)
I've implemented the logic you need below (make sure to click "Run snippet"):
const App = {
el: '#app',
template: `
<div>
<!--
Remember that writing v-model="quantity" is the same as writing :value="quantity" #input="quantity = $event"
(or #input="quanity = $event.target.value" if you put in HTML elements)
You can't use v-model="valueFormatted" here because this would be the same as writing
:value="valueFormatted" #input="valueFormatted = $event.target.value"
So that's a mistake, because valueFormatted is a computed and you can't assign to it
(unless you create a special computed with a setter, but that's not what you need right now)
-->
<select :value="valueFormatted" #input="value = $event.target.value" :disabled="disabled">
<option disabled="disabled" value="">Select nationality</option>
<option v-for="option in options" :value="option">{{option}}</option>
</select>
<hr>
<div>
<button #click="options = ['Scotland']">Make the select have 1 item</button>
<button #click="options = ['Scotland', 'Poland']">Make the seelct have 2 items</button>
</div>
</div>
`,
data() {
return {
options: ["Scotland", "Poland"],
value: '',
}
},
computed: {
disabled() {
return this.options.length < 2
},
/*
* If this.disabled is true, returns the value of the first option
* If it's false, it returns the normal value from data (user selected)
*/
valueFormatted() {
//watch out - this computed will return undefined if this.disabled is true and if options is empty
//to avoid that, you can do for example this:
//return this.disabled === true ? (this.options[0] ?? '' ) : this.value;
return this.disabled === true ? this.options[0] : this.value;
},
},
}
new Vue(App);
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<html>
<body>
<div id="app" />
</body>
</html>
You're probably going to use this select's value later to make eg. an API call, so make sure to send this.valueFormatted instead of this.value

How to save category in laravel 5.7 with vue.js

Using Laravel 5.7 with vuejs, I am trying to display parent_id from a MySQL categories table. I want to pass the name and get all it's child categories irrespective of the parent.
My blade
<form action="{{ route('categories.store') }}" method="post">
#csrf
<div class="form-group">
<label for="name">name:</label>
<input type="text" id="name" class="form-control" v-model="name">
</div>
<div class="form-group">
<label for="sub_category">category</label>
<select id="sub_category" v-model="parent_id" class="form-control">
<option data-display="main category" value="0">main category</option>
<option v-for="category in categories" :value="category.id">#{{ category.name }}</option>
</select>
</div>
<div class="form-group">
<button type="button" #click="addCategory()" class="btn btn-info">save</button>
</div>
</form>
web.php
Route::group(['namespace' => 'Admin', 'prefix' => 'admin'],function (){
$this->get('panel', 'PanelController#index')->name('panel.index');
$this->resource('categories', 'CategoryController');
});
My vue
addCategory: function () {
axios.post(route('categories.store'), {
name: this.name,
parent_id: this.parent_id,
}).then(response => {
this.categories.push({'name': response.data.name, 'id': response.data.id});
}, response => {
this.error = 1;
console.log('Errors');
});
}
CategoryController
public function store(Request $request)
{
$category = new Category();
$category->name = $request->name;
$category->parent_id = $request->parent_id;
if ($category->save()) {
return $category;
}
}
I see this error in console for first
Too
And I get 405 error.
Remove #click from submit buttom.
Remove route... from form action and set it #
Add #submit="addCategory()" to the form
In the axios.post samply add the route without route function.
Update:
If you want to prevent page refreshing, add .prevent after #submit.

remove option from second select if already selected [Ordered multiple selection]

I had select option repeater.
What I want is that when I selected johndoe at the first option, it will no longer display on the second select option.
here's my html
<div id="app">
<h1>Vue JS Multiple Fields Repeater</h1>
<div class="col-sm-6">
<div class="panel panel-default relative has-absolute" v-for="(field, index) in users.usersRepeater">
<button #click="addUsersField" type="button">
Add
</button>
<button #click="deleteUsersField(index)" v-if="field != 0" type="button">
Delete
</button>
<div class="panel-body has-absolute">
<div class="form-group">
<label for="users" class="control-label col-sm-3 text-left">Users {{field}}</label>
<select :name="'users'+index"
class="form-control"
id="users">
<option value="" hidden>Select User</option>
<option value="1">John Doe</option>
<option value="2">Mark Doe</option>
<option value="3">Mae Doe</option>
<option value="4">John Smith</option>
<option value="5">Mae Smith</option>
</select>
</div>
</div>
</div>
</div>
</div>
here's my vue.js
new Vue({
el: '#app',
data: {
users: {
usersRepeater: [{ user: '' }]
}
},
methods: {
addUsersField: function() {
this.users.usersRepeater.push({
user: ''
});
},
deleteUsersField: function(index) {
this.users.usersRepeater.splice(index, 1);
},
}
});
here's the fiddle -> https://jsfiddle.net/0e3csn5y/23/
Ok I have this working now. I liked the question because making an ordered selection is a generic case. But, for me anyway, it wasn't straightforward. The breakthrough was realising that, when you number the choices, the whole state of the component could be encapsulated in one array, allUsers. Available users and choices then become computed properties, based on this array. Moral of the story: get your store right, with no interactions between elements of the store.
My answer weighs in at 130 lines. How long and hard would this be without Vue? Mind boggles.
Stack wants me to post some code, so here's the computed property that generates an array of choices made, in order of their priority, from the all users array...
choices(){
return this.store.allUsers.map((aUser,index)=>{
if(aUser.selection != null)
return {idxAllUsers : index, selection: aUser.selection};
else
return null;
})
.filter(aSelection=>aSelection != null)
.sort((a,b)=>{return a.selection - b.selection})
.map(a=>a.idxAllUsers);
},
I found this one very helpful.

Getting Radio button selection

NO JQUERY! When the user selects Have a Baby or Military leave radio buttons pop up. I am having trouble getting the values of the selected buttons and changing the innerHTML with id="choice" to the value. Can someone please help??
http://jsfiddle.net/73Vq9/
<html>
<head>
<script>
//this function deals with changing the event
function changeMessage(oElement) {
//have a baby
if (oElement.value == "100") {
document.getElementById("btn").style.display = "none";
document.getElementById("radio").style.display = "inline-block";
document.getElementById("rd1").innerHTML = "C-Section";
document.getElementById("rd2").innerHTML = "Regular Birth";
document.getElementById("rd1").value = "C-Section";
document.getElementById("rd2").value = "Regular Birth";
//military leave
} else if (oElement.value == "15") {
document.getElementById("btn").style.display = "none";
document.getElementById("radio").style.display = "inline-block";
document.getElementById("rd1").innerHTML = "Training";
document.getElementById("rd2").innerHTML = "Active Duty";
document.getElementById("rd1").value = "Training";
document.getElementById("rd2").value = "Active Duty";
//no value, the first, blanck value
} else if (oElement.value == "0") {
document.getElementById("btn").style.display = "none";
document.getElementById("radio").style.display = "none";
} else {
document.getElementById("btn").style.display = "inline-block";
document.getElementById("radio").style.display = "none";
}
return;
}
</script>
</head>
<body>
<div style="margin-left:250px;">
<select id="leave" onchange="changeMessage(this);">
<option value="0"></option>
<option value="5">Get Married</option>
<option value="100">Have a Baby</option>
<option value="90">Adopt a Child</option>
<option value="35">Retire</option>
<option value="15">Military Leave</option>
<option value="25">Medical Leave</option>
</select>
<button id="btn" style="display:none" onclick="getInfo()"type="button">Process</button>
</div>
<div id="radio" style="display:none">
<div id="rd1"></div><input type="radio" name="sex" value="" />
<div id="rd2"></div><input type="radio" name="sex" value=""/>
</div>
<div id="choice">Radio Choice</div>
Your input values are never set so will always be null.
When you changed your code in your previous question https://stackoverflow.com/questions/12091968/javascript-function-not-changing-input-types you moved the id from the input to a <div> so your JavaScript is no longer setting the input's value.
You need to change the JavaScript to set the input correctly and then something like:
HTML
<input type="radio" name="sex" value="" onclick="showChoice(this)"/>
JavaScript
function showChoice(input) {
document.getElementById('choice').innerHTML = "Radio Choice=" + input.value;
}
should append the selected input's value in the <div id="choice">