I'm trying to use a component called "Vue-Chartjs" to create a LineChart.[
I'm passing some data from a MySql database to the 'chartData' prop, defined in the Chart.js file.
But I'm getting this error. What I understood (I think), is that chartData doesn't get updated.
Does anyone know why it doesn't work? Thank you very much!
This are my Chart.js file and my Forecast.vue file
import {
Line,
mixins
} from 'vue-chartjs'
const {
reactiveProp
} = mixins
export default {
name: 'line-chart',
extends: Line,
mixins: [reactiveProp],
props: {
chartData: {
type: Array,
required: true
},
chartLabels: {
type: Array,
required: true
}
},
data() {
return {
options: {
scales: {
yAxes: [{
display: true
}],
xAxes: [{
display: false
}]
},
legend: {
display: true
},
responsive: true,
maintainAspectRatio: false
}
}
},
mounted() {
this.renderChart({
labels: this.chartLabels,
datasets: [{
label: 'Temperature',
colors: '#000000',
backgroundColor: '#000000',
data: this.chartData
}]
}, this.options)
}
}
<template>
<div class="FiveDaysForecast">
<div class="tabs is-fullwidth">
<ul>
<li><router-link to="OneDayForecast"><span class="icon is-small"><i class="fas fa-cloud"></i></span>One day forecast</router-link></li>
<li class="is-active"><router-link to="FiveDaysForecast"><span class="icon is-small"><i class="fas fa-cloud"></i></span>Five days forecast</router-link></li>
<li><router-link to="FilterByDate"><span class="icon is-small"><i class="fas fa-calendar-alt"></i></span>Filter forecast by date</router-link></li>
</ul>
</div>
<h1>FIVE DAYS FORECAST</h1>
<form>
<div class="box">
<div class="field">
<div class="control">
<input class="input is-rounded" type="text" placeholder="Place" v-model="place">
</div>
<br>
<div class="control">
<input class="input is-rounded" type="text" placeholder="Country" v-model="country">
</div>
<br>
<div class="control">
<input class="input is-rounded" type="text" placeholder="Unit of measure (Celsius = 'metric' | Fahrenheit = 'imperial')" v-model="unitOfMeasure" required>
</div>
<br>
<div class="control">
<input class="input is-rounded" type="text" placeholder="Latitude" v-model="latitude">
</div>
<br>
<div class="control">
<input class="input is-rounded" type="text" placeholder="Longitude" v-model="longitude">
</div>
</div>
<button class="button is-medium is-rounded" #click="getFiveDaysForecast">Search</button>
</div>
</form>
<br>
<table class="table is-narrow">
<thead>
<tr>
<th>Temperature</th>
<th>TemperatureMin</th>
<th>TemperatureMax</th>
<th>Humidity</th>
<th>Pressure</th>
<th>Time</th>
</tr>
</thead>
<tbody>
<tr v-for="forecast in forecastData" :key="forecast.Pressure">
<td>{{forecast.temperature}}</td>
<td>{{forecast.temperatureMin}}</td>
<td>{{forecast.temperatureMax}}</td>
<td>{{forecast.humidity}}</td>
<td>{{forecast.pressure}}</td>
<td>{{forecast.timeStamp}}</td>
</tr>
</tbody>
</table>
<line-chart
:chart-data="tempRows"
:chartLabels="weatherDate"
></line-chart>
</div>
</template>
<script>
import axios from "axios";
export default {
name: "FiveDaysForecast",
data() {
return {
place: "",
country: "",
unitOfMeasure: "",
latitude: "",
longitude: "",
forecastData: [],
temperature: [],
weatherDate: [],
tempRows: []
};
},
methods: {
getFiveDaysForecast() {
axios({
method: "get",
url: "http://localhost:55556/api/ForecastActions/fiveDaysForecast",
params: {
Place: this.place,
Country: this.country,
UnitOfMeasure: this.unitOfMeasure,
Lat: this.latitude,
Lon: this.longitude
}
})
.then(response => {
console.log(response);
this.forecastData = response.data;
this.forecastData.forEach(item => {
var tempArray = [];
this.tempRows.push(item.temperature);
this.weatherDate.push(item.timeStamp);
});
})
.catch(error => {
console.log(error);
});
}
}
};
</script>
<style scoped>
.FiveDaysForecast {
width: 1200px;
margin: 30px auto;
}
.tabs {
width: 600px;
margin-left: auto;
margin-right: auto;
}
h1 {
font-size: 50px;
}
#forecast-params {
margin-top: 30px;
margin-bottom: 50px;
text-align: left;
font-size: 20px;
}
.param-names {
font-weight: bold;
color: black;
font-size: 20px;
}
.box {
background-color: transparent;
width: 600px;
margin: 0 auto;
border: 3px solid royalblue;
box-shadow: 0px 0px 30px royalblue;
}
::placeholder {
color: rgb(170, 170, 170);
}
input,
button {
background-color: #fcfcfc;
border: 2px solid rgb(170, 170, 170);
}
input:focus {
border: 2px solid royalblue;
box-shadow: 0px 0px 30px royalblue;
}
input:hover {
border: 2px solid royalblue;
}
button:focus {
border: 2px solid royalblue;
box-shadow: 0px 0px 30px royalblue;
}
button:hover {
border: 2px solid royalblue;
}
.table {
margin: 0 auto;
width: 1000px;
}
td,
th {
text-align: center;
}
thead {
font-size: 20px;
display: table-header-group;
vertical-align: middle;
border-bottom: 3px solid royalblue !important;
}
tr {
font-weight: 600;
transition: background-color 0.5s ease;
}
tr:hover {
background-color: rgb(153, 179, 255);
}
#chart {
display: inline-block;
padding: 0px;
margin: 0px;
}
#tempChart {
padding: 0 auto;
}
#charts {
padding: 0px auto;
}
</style>
Well your "problem" is that your data is async. So the chart will be rendered without any data or without proper data.
You have to put a
v-if="loaded"
on your chart component.
And in your axios call you need to set it to true.
Related
I used the Composition API when migrating the project from vue2.x to vue3.0, but the page does not work properly, in vue3.0
The environment prompts me to have an "Unexpected mutation of "task" prop" error, I want to know how to write the correct compos API
This is Vue2.x code
<template>
<transition name="fade">
<div class="task" v-if="!task.deleted">
<input :id="id" type="checkbox" v-model="task.done" />
<label :for="id">{{ task.title }}</label>
<transition name="fade">
<span
class="task_delete"
v-show="task.done"
#click="deleteTask({ task })"
>
<i class="fa fa-trash"></i>
</span>
</transition>
</div>
</transition>
</template>
<script>
import { mapMutations } from "vuex";
let GID = 1;
export default {
props: {
task: {
type: Object,
required: true,
},
},
data() {
return {
id: `task-${GID++}`,
};
},
methods: {
...mapMutations(["deleteTask"]),
},
};
</script>
<style lang="scss">
.task {
display: flex;
padding: 12px 0;
border-bottom: 1px solid #eee;
font-size: 14px;
}
.task input {
display: none;
}
.task label {
flex: 1;
line-height: 20px;
}
.task label:before,
.task label:after {
content: "";
display: inline-block;
margin-right: 20px;
margin-top: 1px;
width: 14px;
height: 14px;
vertical-align: top;
}
.task label:before {
border: 1px solid #ccc;
border-radius: 2px;
background-color: white;
}
.task label:after {
content: "\f00c";
position: relative;
display: none;
z-index: 10;
margin-right: -16px;
width: 10px;
height: 10px;
padding: 3px;
border-radius: 2px;
font: normal normal normal 10px/1 FontAwesome;
color: white;
background-color: #ccc;
float: left;
}
.task input:checked + label:after {
display: inline-block;
}
.task_delete {
padding: 0 10px;
color: #ccc;
font-size: 16px;
}
.fade-leave-to,
.fade-enter {
opacity: 0;
}
.fade-enter-to,
.fade-leave {
opacity: 1;
}
.fade-enter-active,
.fade-leave-active {
transition: all 0.3s ease;
}
</style>
This is Vue3.0 code use Composition API, but not work
<template>
<transition name="fade">
<div class="task" v-if="!data.task.deleted">
<input :id="id" type="checkbox" v-model="data.task.done" />
<label :for="id">{{ data.task.title }}</label>
<transition name="fade">
<span
class="task_delete"
v-show="data.task.done"
#click="deleteTask({ task })"
>
<i class="fa fa-trash"></i>
</span>
</transition>
</div>
</transition>
</template>
<script>
import { reactive } from "vue";
import { mapMutations } from "vuex";
let GID = 1;
export default {
name: "Task",
props: {
task: {
type: Object,
required: true,
},
},
setup(props) {
const data = reactive({
task: props.task,
id: `task-${GID++}`,
});
return { data };
},
methods: {
...mapMutations(["deleteTask"]),
},
};
</script>
<style lang="scss">
.task {
display: flex;
padding: 12px 0;
border-bottom: 1px solid #eee;
font-size: 14px;
}
.task input {
display: none;
}
.task label {
flex: 1;
line-height: 20px;
}
.task label:before,
.task label:after {
content: "";
display: inline-block;
margin-right: 20px;
margin-top: 1px;
width: 14px;
height: 14px;
vertical-align: top;
}
.task label:before {
border: 1px solid #ccc;
border-radius: 2px;
background-color: white;
}
.task label:after {
content: "\f00c";
position: relative;
display: none;
z-index: 10;
margin-right: -16px;
width: 10px;
height: 10px;
padding: 3px;
border-radius: 2px;
font: normal normal normal 10px/1 FontAwesome;
color: white;
background-color: #ccc;
float: left;
}
.task input:checked + label:after {
display: inline-block;
}
.task_delete {
padding: 0 10px;
color: #ccc;
font-size: 16px;
}
.fade-leave-to,
.fade-enter {
opacity: 0;
}
.fade-enter-to,
.fade-leave {
opacity: 1;
}
.fade-enter-active,
.fade-leave-active {
transition: all 0.3s ease;
}
</style>
I think the problem is you're using v-model for props on checkbox, it will change props value directly and vue not allow it. Try update props value manual by emit event. And u dont need to use props with reactive in child component, but need to reactive that props in parent component
<input :id="id" type="checkbox" v-value="task.done" #change="updateCheckbox($event)")/>
In script:
export default {
name: "Task",
props: {
task: {
type: Object,
required: true,
},
},
emits: ['updateCheckbox'],
setup(props) {
const data = reactive({
id: `task-${GID++}`,
});
return { data };
},
methods: {
updateCheckbox(e) {
this.$emit('updateCheckbox', e.target.value)
}
},
};
I am trying to create a paginated flexbox using data from an API but struggle with it although I read the setup step-by step.
Here is my code without styles:
<template>
<div id="app">
<paginate name="articles" :list="articles" class="paginate-list">
<li v-for="item in paginated('articles')">
{{ item }}
</li>
</paginate>
<paginate-links for="items" :show-step-links="true"></paginate-links>
<paginate-links for="items" :limit="2" :show-step-links="true">
</paginate-links>
<paginate-links for="items" :simple="{ next: 'Next »', prev: '« Back' }">
</paginate-links>
</div>
</template>
<script>
import axios from 'axios';
import VuePaginate from 'vue-paginate'
export default {
data() {
return {
items:[],
paginate: [articles]
}
},
created() {
axios.get(https://zbeta2.mykuwaitnet.net/backend/en/api/v2/media-center/press-release/?page_size=61&type=5)
.then(response => {
this.items = response.data
})
}
}
</script>
Step 1: Install npm install --save vue-paginate
Step 2: Import vue-paginate component in main.js
import VuePaginate from "vue-paginate";
Vue.use(VuePaginate);
Step 3: HTML template will be like,
<template>
<div id="app">
<paginate ref="paginator" class="flex-container" name="items" :list="items">
<li
v-for="(item, index) in paginated('items')"
:key="index"
class="flex-item">
<h4>{{ item.pub_date }}, {{ item.title }}</h4>
<img :src="item.image && item.image.file" />
<div class="downloads">
<span
v-for="downloadable in item.downloadable.filter(
(d) => !!d.document_en
)"
:key="downloadable.id">
<a :href="downloadable.document_en.file">Download</a>
</span>
</div>
</li>
</paginate>
<paginate-links
for="items"
:limit="2"
:show-step-links="true"></paginate-links>
</div>
</template>
Step 4: Your component script like
<script>
import axios from "axios";
export default {
data() {
return {
items: [],
paginate: ["items"],
};
},
created() {
this.loadPressRelease();
},
methods: {
loadPressRelease() {
axios.get(`https://zbeta2.mykuwaitnet.net/backend/en/api/v2/media-center/press-release/?page_size=61&type=5`)
.then((response) => {
this.items = response.data.results;
});
}
}
};
</script>
Step 5: CSS style
<style>
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
ul.flex-container {
padding: 0;
margin: 0;
list-style-type: none;
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-webkit-flex-flow: row wrap;
flex-direction: row wrap;
flex-wrap: wrap;
justify-content: space-around;
}
li img {
display: initial;
height: 100px;
}
.flex-item {
background: tomato;
width: calc(100% / 3.5);
padding: 5px;
height: auto;
margin-top: 10px;
color: white;
font-weight: bold;
text-align: center;
}
.downloads {
margin-top: 10px;
}
ul.paginate-links.items li {
display: inline-block;
margin: 5px;
}
ul.paginate-links.items a {
cursor: pointer;
}
ul.paginate-links.items li.active a {
font-weight: bold;
}
ul.paginate-links.items li.next:before {
content: " | ";
margin-right: 13px;
color: #ddd;
}
ul.paginate-links.items li.disabled a {
color: #ccc;
cursor: no-drop;
}
</style>
DEMO Link
in vuejs i cant make grid css with v-for , i used template-grid-columns so i can have 3 divs in same row but the result was just one div in one row and this is not the result i want, so is there any optimal solution i can use, here is the code
this is the html part :
<template>
<div>
<div>
<select class="select" v-model="status">
<option value="onSale">onSale</option>
<option value="featured">featured</option>
</select>
<caption>Total {{computedProducts.length}} Products</caption>
<div class ="productListing" v-for="(product, index) in computedProducts" :key="index">
<div class="singleProduct box effect1">
<h1>{{product.name}}</h1>
<h1></h1>{{product.color}}
{{product.featured}}
</div>
</div>
</div>
</div>
</template>
vuejs part :
<script>
// # is an alias to /src
export default {
name: 'home',
data() {
return {
status: [],
products: [
{name:'test1', color:'red', size:'XL',status:"featured"},
{name:'test2', color:'black', size:'L',status:"onSale"},
{name:'test3', color:'red', size:'L',status:"featured"},
],
}
},
computed: {
computedProducts: function () {
return this.products.filter((item) => {
return (this.status.length === 0 || this.status.includes(item.status))
})
}
}
}
</script>
css part :
<style lang="scss" scoped>
.productListing {
display: grid;
grid-template-columns: 1fr 1fr
}
.box {
background:#FFF;
margin:40px auto;
}
/*==================================================
* Effect 1
* ===============================================*/
.effect1{
-webkit-box-shadow: 0 10px 6px -6px #777;
-moz-box-shadow: 0 10px 6px -6px #777;
box-shadow: 0 10px 6px -6px #777;
}
$green: #2ecc71;
$red: #e74c3c;
$blue: #3498db;
$yellow: #f1c40f;
$purple: #8e44ad;
$turquoise: #1abc9c;
.select {
border: 0.1em solid #FFFFFF;
margin: 0 0.3em 0.3em 0;
border-radius: 0.12em;
box-sizing: border-box;
text-decoration:none;
font-family:'Roboto',sans-serif;
}
</style>
thank you in advance for your help
You grid effect would appear under it children instead of itself.
You need to add one parent div for your products, like below
<div class="productListing">
<div v-for="(product, index) in computedProducts" :key="index">
......
</div>
</div>
CSS would be
.productListing {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
I'm learning how to use vue.js to pull movie information and display it.
Inside the main application mc I have a method getMovie which isn't being called when another method updateMovie is called. The updateMovie method is called from the event 'switch' which is emitted by a child component details-card
I can see that the title on my application gets changed and the method updateMovie is working if you click on a director and then a movie under that director. The input field also changes value. Why won't the getMovie work?
var mc = new Vue({
el: "#movie-card",
data: {
title: '',
valid: false,
loading: false,
error: false,
mc: {},
directorArray: [],
actorArray: [],
},
computed: {
checkMulti: function(item) {
if (Object.keys(item).length <= 1) {
return false;
} else {
return true;
}
}
},
methods: {
getMovie: function() {
this.cm = {};
console.log("getMovie called")
if (this.title !== "") {
this.loading = true;
this.error = false;
searchString = 'https://www.omdbapi.com/?t=' + this.title;
var that = this;
axios.get(searchString)
.then(function(res) {
that.cm = res.data;
that.directorArray = res.data.Director.trim().split(/\s*,\s*/);
that.actorArray = res.data.Actors.trim().split(/\s*,\s*/);
that.valid = true;
that.loading = false;
})
.catch(function(error) {
console.log(error.message);
that.loading = false;
that.error = true;
})
}
},
updateMovie: function(movie) {
console.log(movie);
this.title = movie;
this.getMovie;
}
}
})
Vue.component('details-card', {
props: [
'name',
'title'
],
template: `
<div>
<a href=""
#click="handleShowDetails($event)"
>
{{ name }}
</a>
<div v-if="visible" class="detailsCard">
<h3 class="removeTopMargin">{{ name }}</h3>
<img :src="picUrl">
<h4>Known for</h4>
<p v-for="movie in knownForArray">
<a href=""
#click="switchMovie(movie.original_title, $event)"
>{{ movie.original_title }}</a>
</p>
</div>
</div>
`,
data: function() {
return {
picUrl: "",
knownForArray: [],
visible: false
}
},
methods: {
handleShowDetails: function($event) {
this.visible = !this.visible;
this.callPic($event);
},
switchMovie( movie , $event) {
if ($event) $event.preventDefault();
console.log("switching to...", movie);
this.$emit('switch', movie);
},
callPic: function(event) {
if (event) event.preventDefault();
let that = this;
let searchString = "https://api.themoviedb.org/3/search/person?api_key=9b8f2bdd1eaf20c57554e6d25e0823a2&language=en-US&query=" + this.name + "&page=1&include_adult=false";
if (!this.picUrl) { //only load if empty
axios.get(searchString)
.then(function(res) {
let profilePath = res.data.results[0].profile_path;
if (profilePath === null) {
that.picUrl = "http://placehold.it/150x200"
} else {
that.picUrl = 'https://image.tmdb.org/t/p/w150/' + profilePath;
}
that.personPic = profilePath;
that.knownForArray = res.data.results[0].known_for;
}).catch(function(err){
console.log(err);
})
}
},
hideDetails: function () {
this.visible= false;
}
}
})
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
*:focus {
outline: none;
}
ul {
padding-left: 1em;
}
.loading {
margin: auto;
max-width: 450px;
}
.details {
display:block;
margin: 1em auto;
text-align: center;
}
.searchBar {
padding: .5em;
-webkit-box-shadow: 0px 2px 16px 2px rgba(168,168,168,0.45);
-moz-box-shadow: 0px 2px 16px 2px rgba(168,168,168,0.45);
box-shadow: 0px 2px 16px 2px rgba(168,168,168,0.45);
text-align: center;
}
.searchBar input {
padding: .5em;
width: 300px;
font-size: 1em;
border: none;
border-bottom: 1px solid gray;
}
.searchBar button {
padding: .2em;
border: 2px solid gray;
border-radius: 8px;
background: white;
font-size: 1em;
color:#333;
}
img {
display: block;
margin: auto;
width: 150px;
padding-bottom: .33em;
}
.card {
max-width: 500px;
margin: 2em auto;
-webkit-box-shadow: 0px 6px 16px 2px rgba(168,168,168,0.45);
-moz-box-shadow: 0px 6px 16px 2px rgba(168,168,168,0.45);
box-shadow: 0px 6px 16px 2px rgba(168,168,168,0.45);
padding: 2em;
}
.detailsCard {
-webkit-box-shadow: 0px 6px 16px 2px rgba(168,168,168,0.45);
-moz-box-shadow: 0px 6px 16px 2px rgba(168,168,168,0.45);
box-shadow: 0px 6px 16px 2px rgba(168,168,168,0.45);
padding: 1em;
}
/* ======= Typography */
html {font-size: 1em;}
body {
background-color: white;
font-family: roboto;
font-weight: 400;
line-height: 1.45;
color: #333;
}
p {margin-bottom: 1.3em;}
h1, h2, h3, h4 {
margin: 1.414em 0 0.5em;
font-weight: inherit;
line-height: 1.2;
}
h2, h3, h4 {
border-bottom: 1px solid gray;
}
h1 {
margin-top: 0;
font-size: 3.998em;
text-align: center;
}
h2 {font-size: 2.827em;}
h3 {font-size: 1.999em;}
h4 {font-size: 1.414em;}
small, .font_small {font-size: 0.707em;}
.removeTopMargin {
margin-top: .5em;
}
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<div id="movie-card">
<div class="searchBar">
<input type="text" ref="input" v-model="title" placeholder="Enter a movie title here..." v-on:keyup.enter="getMovie">
<button type="submit" #click="getMovie">Search</button>
</div>
<div class="loading" v-if="loading">
<BR><BR>
<h1>Loading...</h1>
</div>
<div class="loading" v-if="error">
<BR><BR>
<h1>Something went wrong!</h1>
</div>
<div class="card" v-if="valid && !loading">
<h1> {{ cm.Title }}</h1>
<div v-if="!(cm.Poster === 'N/A')" class="poster">
<img v-bind:src="cm.Poster">
</div>
<div class="details">
<p>{{ cm.Year + " – " + cm.Rated + " – " + cm.Runtime }}</p>
</div>
<p>{{ cm.Plot }}</p>
<div class="directors" v-if="cm.Director">
<h3 v-if="(directorArray.length > 1)">Director</h3>
<h3 v-else>Director</h3>
<p>
<p v-for="(director, index) in directorArray">
<details-card :name="director" v-on:switch="updateMovie"></details-card>
</p>
</p>
</div>
<div class="actors" v-if="cm.Actors">
<h3 v-if="actorArray.length > 1">Actors</h3>
<h3 v-else>Actor</h3>
<p>
<p v-for="(actor, index) in actorArray">
<details-card :name="actor"></details-card>
</p>
</p>
</div>
<div class="ratings" v-if="cm.Ratings">
<h3>Ratings</h3>
<ul>
<li v-for="rating in cm.Ratings">{{ rating.Source }}: {{ rating.Value }}</li>
</ul>
</div>
</div>
</div>
I have a view with a partial view. In my main view there's a dropdown list, on selection of a value from dropdown list, WebGrid is populated according to the choice selected.
Also in the main view I have a dropdown list, a datetime picker text box, and a Submit (Allocate) button.
Webgrid has one check box for each row. On selecting a row from WebGrid, collected data needs to go the controller. But my button ain't working!
Please help me with my controller, I'm not able to get selected values in my controller.
My View is like:
#model LipiProject.Models.Allocation
#{
ViewBag.Title = "Call Allocation";
}
<script src="~/Scripts/jquery-1.8.2.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
<link href="~/StyleSheet1.css" rel="stylesheet" />
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script src="~/Scripts/Timepicker.js"></script>
<script>
$(function () {
$("#datepicker").datetimepicker({ timeFormat: "hh:mm tt" });
});</script>
<style>
.webgrid-table {
font-family: Arial,Helvetica,sans-serif;
font-size: 14px;
font-weight: normal;
width: 650px;
display: table;
border-collapse: collapse;
border: solid 1px #C5C5C5;
background-color: white;
}
.webgrid-table td, th {
border: 1px solid #C5C5C5;
padding: 3px 7px 2px;
}
.webgrid-header, .webgrid-header a {
background-color: #0094ff;
color:#ffffff;
text-align: left;
text-decoration: none;
}
.webgrid-footer {
}
.webgrid-row-style {
padding: 3px 7px 2px;
}
.webgrid-alternating-row {
background-color:azure;
padding: 3px 7px 2px;
}
.col1Width {
width: 55px;
}
.col2Width {
width: 220px;
}
.lineSep {
border-bottom: 1px solid #000;
display: block;
margin: 10px 0;
}
</style>
<h2>Index</h2>
<div id="overlay" style="display: none">
<img id="loading" src="~/Images/ajax-loader.gif">
</div>
#using (Html.BeginForm("CallAllocationSubmit", "Home", FormMethod.Post, new { id = "FrmCallAllocate", ReturnUrl = ViewBag.ReturnUrl }))
{
<table>
<tr>
<td>
<div class="row">
<div class="col-sm-12">
<section class="panel default blue_title h5">
<div class="panel-heading">Select Call Category</div>
<div class="panel-body">
#Html.DropDownList("CallNature", Model.CallNature, "Select Call Nature")
</div>
</section>
</div>
</div>
</td>
</tr>
<tr>
<td>
<div id="GridView">
#Html.Partial("_CallAllocation",Model.CallTicketGrid)
</div>
</td>
</tr>
</table>
<div class="row">
<div class="col-sm-12">
<section class="panel default blue_title h5">
<div class="panel-heading">Allocate Engineer</div>
<div class="panel-body">
#Html.DropDownList("DefaultEngg", Model.DefaultEngg, "Select Engineer")
ETA: <input type="text" id="datepicker">
<input type="submit" value="Allocate" class="btn btn-primary">
</div>
</section>
</div>
</div>
}
<script type="text/javascript">
$('#CallNature').change(function (e) {
e.preventDefault();
var url = '#Url.Action("Filter")';
$.get(url, { CallNatureId: $(this).val() }, function (result) {
debugger;
$('#GridView').html(result);
});
});
</script>
My Partial View is like:
#model List<LipiProject.Models.Allocation>
#{
ViewBag.Title = "_CallAllocation";
}
<style>
.webgrid-table {
font-family: Arial,Helvetica,sans-serif;
font-size: 14px;
font-weight: normal;
width: auto;
display: table;
border-collapse: collapse;
border: solid 1px #C5C5C5;
background-color: white;
}
.webgrid-table td, th {
border: 1px solid #C5C5C5;
padding: 3px 7px 2px;
}
.webgrid-header, .webgrid-header a {
background-color: #0094ff;
color:#ffffff;
text-align: left;
text-decoration: none;
}
.webgrid-footer {
}
.webgrid-row-style {
padding: 3px 7px 2px;
}
.webgrid-alternating-row {
background-color:azure;
padding: 3px 7px 2px;
}
.col1Width {
width: 55px;
}
.col2Width {
width: 220px;
}
.lineSep {
border-bottom: 1px solid #000;
display: block;
margin: 10px 0;
}
</style>
#{ var grid = new WebGrid(source: Model, canPage: true, rowsPerPage: 10, ajaxUpdateContainerId: "gridContent", columnNames: new[] { "CallTicketNumber", "TicketDate", "SerialNumber", "CustomerName", "City", "State", "DefaultEngg" }, defaultSort: "DateCreated");
<div class="row" id="GridView">
<div class="col-sm-12">
<section class="panel default blue_title h5">
<div class="panel-heading">Allocate Calls</div>
<div class="panel-body">
<div class="col-sm-12">#grid.GetHtml(mode:WebGridPagerModes.All,
tableStyle: "webgrid-table",
htmlAttributes: new {id = "checkableGrid"},
headerStyle: "webgrid-header",
footerStyle: "webgrid-footer",
alternatingRowStyle: "webgrid-alternating-row",
selectedRowStyle: "webgrid-selected-row",
rowStyle: "webgrid-row-style",
columns: grid.Columns(
grid.Column(columnName: "CallTicketNumber", header: "CallTicketNumber"),
grid.Column(columnName: "TicketDate", header: "Ticket Logged On"),
grid.Column(columnName: "SerialNumber", header: "Serial Number"),
grid.Column(columnName: "CustomerName", header: "Customer Name"),
grid.Column(columnName: "City", header: "City"),
grid.Column(columnName: "State", header: "State"),
//grid.Column("DefaultEngg", "Engineer", format:item => Html.DropDownList(((string)item.DefaultEngg).ToString(), (List<SelectListItem>)Model[0].DefaultEngg))
//grid.Column(header:"Default Engineer", format: item =>Html.DropDownList(((long)item.CallTicketNumber).ToString(), (IEnumerable<SelectListItem>)Model[0].DefaultEngg))
grid.Column(format: #<text> <input type="checkbox" value="#item.CallTicketNumber" name="ids" /> </text>,
header: "SelectAll")
)) </div>
</div>
</section>
</div>
</div>
}
<script>
$(document).ready(function () {
// 1st replace first column header text with checkbox
$("#checkableGrid th").each(function () {
if ($.trim($(this).text().toString().toLowerCase()) === "SelectAll") {
$(this).text('');
$("<input/>", { type: "checkbox", id: "cbSelectAll", value: "" }).appendTo($(this));
$(this).append("<span>Select All</span>");
}
});
//2nd click event for header checkbox for select /deselect all
$("#cbSelectAll").live("click", function () {
var ischecked = this.checked;
$('#checkableGrid').find("input:checkbox").each(function () {
this.checked = ischecked;
});
});
//3rd click event for checkbox of each row
$("input[name='ids']").click(function () {
var totalRows = $("#checkableGrid td :checkbox").length;
var checked = $("#checkableGrid td :checkbox:checked").length;
if (checked == totalRows) {
$("#checkableGrid").find("input:checkbox").each(function () {
this.checked = true;
});
}
else {
$("#cbSelectAll").removeAttr("checked");
}
});
});
</script>
My Controller is like:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CallAllocationSubmit(Allocation allocate, FormCollection frmCollection)
{
string CallTicketNumber = frmCollection["CallTicketNumber"].ToString();
string CallNature = frmCollection["CallNature"].ToString();
var Defengg = frmCollection["DefaultEngg"].ToList();
var ETA = frmCollection["ETA"].ToString();
return RedirectToAction("CallAllocation");
}