I trying to use morris area chart, I don't know how correctly to serialize data and send date which morris area chart can understand.
This is method in HomeController which get data from DB.
public ActionResult GetData()
{
List<GraphData> GraphDataList = new List<GraphData>();
var user = db.Users.Where(p => p.Email == User.Identity.Name).Single();
var Requests = db.Transactions.Where(p => p.Package_id != null && p.User_id == user.Id);
DateTime day = new DateTime();
int CountPerDay = 0;
// count of request per day
foreach (var request in Requests)
{
if (day.Year == request.Date.Year && day.Day == request.Date.Day)
{
CountPerDay++;
}
else
{
// To 2016-12-03 format of date
string Date = day.Year + "-" + day.Month + "-" + day.Day;
GraphDataList.Add(new GraphData(Date, CountPerDay));
CountPerDay = 0;
day = request.Date;
}
}
// First elem in list is wrong
GraphDataList.RemoveAt(0);
return Json(GraphDataList, JsonRequestBehavior.AllowGet);
}
GraphData class
public class GraphData
{
public string label { get; set; }
public int value { get; set; }
public GraphData(string label, int value)
{
this.label = label;
this.value = value;
}
public GraphData()
{
}
}
Area chart in html code
<div class="col-lg-6">
<div class="panel panel-default">
<div class="panel-heading">
Request statistic
</div>
<!-- /.panel-heading -->
<div class="panel-body">
<div id="area-example"></div>
</div>
<!-- /.panel-body -->
</div>
<!-- /.panel -->
</div>
And func which get data from controller and send to Morris.Area
<!--Get Data for Graph-->
<script type="text/javascript">
$(document).ready(function() {
$.get('#Url.Action("GetData","Home")', function (result) {
new Morris.Area({
// ID of the element in which to draw the chart.
element: 'area-example',
// Chart data records -- each entry in this array corresponds to a point on
// the chart.
data: [result],
// The name of the data record attribute that contains x-values.
xkey: 'label',
ykeys: ['value'],
labels: ['Success requests'],
pointSize: 2,
hideHover: 'auto',
resize: true
});
});
});
</script>
So the result is the clear panel without graph
But if a init data like this
<!--Get Data for Graph-->
<script type="text/javascript">
$(document).ready(function() {
$.get('#Url.Action("GetData","Home")', function (result) {
new Morris.Area({
// ID of the element in which to draw the chart.
element: 'area-example',
// Chart data records -- each entry in this array corresponds to a point on
// the chart.
data: [
{ label: '2016-12-3', value: 150},
{ label: '2016-12-4', value: 221},
{ label: '2016-12-5', value: 43},
{ label: '2016-12-6', value: 21},
{ label: '2016-12-7', value: 312}
],
// The name of the data record attribute that contains x-values.
xkey: 'label',
ykeys: ['value'],
labels: ['Success requests'],
pointSize: 2,
hideHover: 'auto',
resize: true
});
});
});
</script>
the result is
Solution is to use this, because you have already returned a json array using ajax call. So, you do not need data:[result],all you need is data:result.
new Morris.Area({
// ID of the element in which to draw the chart.
element: 'area-example',
// Chart data records -- each entry in this array corresponds to a point on
// the chart.
data: result,
// The name of the data record attribute that contains x-values.
xkey: 'label',
ykeys: ['value'],
labels: ['Success requests'],
pointSize: 2,
hideHover: 'auto',
resize: true
});
Related
I am using a 'Custom Datatable' solution in order to modify picklist values within a datatable. Project code may be referenced here:
https://live.playg.app/play/picklist-in-lightning-datatable
I have made changes so that I can retrieve data from the custom object: Payment__c, and I am attempting modify the picklist values for the Payment_Status__c field. My 'debugging' method has been to create numerous console.log statements to verify data during the updating process. Picklist values are currently hardcoded (have not figured out how to dynamically pull from SF yet). Inline edit of individual cells works fine, and I am able to save those values as well (though changes are not reflected until I perform a manual page refresh). Picklist selection is working, but I am unable to save the currently selected picklist value in the datatable.
I believe that the intended trigger event for picklist selection changes--'valueselect', is not being fired, and the handleSelection method is not receiving this event when a new picklist selection is made.
The lightning component used on Salesforce is c-customDatatableDemo:
customDatatableDemo.js
import { LightningElement, track, wire } from 'lwc';
import getPayments from '#salesforce/apex/PaymentController.getPayments';
import saveRecords from '#salesforce/apex/PaymentController.saveRecords';
import { updateRecord } from 'lightning/uiRecordApi';
import { refreshApex } from '#salesforce/apex';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
export default class CustomDatatableDemo extends LightningElement {
#track data = [];
//have this attribute to track data changed
//with custom picklist or custom lookup
#track draftValues = [];
#track lastSavedData = [];
connectedCallback() {
this.columns = [
{
label: 'Name',
fieldName: 'Name',
editable: false
}, {
label: 'Invoice Number',
fieldName: 'Invoice_Number__c',
editable: true
}, {
label: 'Invoice Amount',
fieldName: 'Invoice_Amount__c',
type: 'currency',
editable: true
}, {
label: 'Invoice Date',
fieldName: 'Invoice_Date__c',
type: 'date',
editable: true
}, {
label: 'Payment Status',
fieldName: 'Payment_Status__c',
type: 'picklist',
typeAttributes:
{
placeholder: 'Choose Status',
options: [
{ label: 'Needs to Be Paid', value: 'Needs to Be Paid' },
{ label: 'Issued', value: 'Issued' },
{ label: 'Voided', value: 'Voided' },
] // List of Payment Status picklist options
, value: {fieldName: 'Payment_Status__c' } // default value for picklist
, context: {fieldName: 'Id' } // binding Payment Id with context variable to be returned back
}
},
{
label: 'Description', fieldName: 'Work_Description__c', type: 'text', editable: true
}];
// Get Payments data
getPayments()
.then(result => {
this.data = result;
this.error = undefined;
})
.catch(error => {
this.error = error;
this.data = undefined;
})
// Save last saved copy
this.lastSavedData = JSON.parse(JSON.stringify(this.data));
}
updateDataValues(updateItem) {
console.log('START--updateDataValues()');
let copyData = [... this.data];
copyData.forEach(item => {
if (item.Id === updateItem.Id) {
for (let field in updateItem) {
console.log('updateDataValues() item.Id = ' + JSON.stringify(updateItem.Id));
console.log('updateItem[field] = ' + JSON.stringify(updateItem[field]));
item[field] = updateItem[field];
console.log('UPDATED--item[field] = ' + updateItem[field]);
}
}
});
//write changes back to original data
this.data = [...copyData];
console.log('this.data = ' + JSON.stringify(this.data));
let tempData = [...this.data];
//console.log('tempData = ' + JSON.stringify(tempData));
console.log('END--updateDataValues()');
}
updateDraftValues(updateItem) {
console.log('START--updateDraftValues()');
console.log('stringify draft updateItem = ' + JSON.stringify(updateItem));
let draftValueChanged = false;
let copyDraftValues = [...this.draftValues];
//store changed value to do operations
//on save. This will enable inline editing &
//show standard cancel & save button
let i = 0;
copyDraftValues.forEach(item => {
if (item.Id === updateItem.Id) {
i++;
console.log('i = ' + i);
for (let field in updateItem) {
console.log(i + '. UpdateDraftValues--item id if selected...item Id = ' + item.Id + ' & item value = ' + item.value);
item[field] = updateItem[field];
console.log('item[field] = ' + updateItem[field]);
}
draftValueChanged = true;
console.log('draftValueChanged = TRUE');
}
});
//draftValueChanged = true;
if (draftValueChanged) {
console.log('YESdraftValueChanged');
console.log('copyDraftValues = ' + JSON.stringify(copyDraftValues));
this.draftValues = [...copyDraftValues];
//console.log('draftValues = ' + JSON.stringify(draftValues));
} else {
console.log('NOdraftValue!Changed');
this.draftValues = [...copyDraftValues, updateItem];
let testDraftValues = {... this.draftValues};
console.log('JSON.stringify(testDraftValues) = ' + JSON.stringify(testDraftValues));
}
console.log('STOP--updateDraftValues()')
}
//listener handler to get the context and data
//updates datatable
picklistChanged(event) {
console.log('START--picklistChanged()');
console.log('EVENT type - ' + event.type);
event.stopPropagation();
let dataReceived = event.detail.data;
let updatedItem = { ...dataReceived };
console.log('picklistChanged()...updatedItem = ' + JSON.stringify(updatedItem));
this.updateDraftValues(updatedItem);
this.updateDataValues(updatedItem);
/* console.log('event.value = ' + event.value);
this.value = event.target.value;
event.stopPropagation();
let dataReceived = event.detail.data;
let updatedItem = { ...dataReceived };
console.log('updatedItem.context ' + updatedItem.context);
console.log('updatedItem.value ' + updatedItem.value);
console.log('updatedItem = ' + JSON.stringify(updatedItem));
this.updateDraftValues(updatedItem);
this.updateDataValues(updatedItem);
console.log('picklistChanged() = ' + JSON.stringify(updatedItem)); */
console.log('STOP--picklistChanged()');
}
handleSelection(event) {
console.log('START--handleSelection()');
this.updateDraftValues(event.detail.draftValues[0]);
console.log('this.updateDraftValues(event.detail.draftValues[0]);')
/* event.stopPropogation();
let dataReceived = event.detail.data;
let updatedItem = { ...dataReceived };
this.updateDraftValues(updatedItem);
this.updateDraftValues(updatedItem); */
console.log('STOP--handleSelection() = ' + JSON.stringify(updatedItem));
}
//handler to handle cell changes & update values in draft values
handleCellChange(event) {
console.log('START--handleCellChange()');
console.log('handleCellChange');
this.updateDraftValues(event.detail.draftValues[0]);
console.log('handleCellChange value = ' + JSON.stringify(this.updateDraftValues));
console.log('END--handleCellChange()');
}
handleSave(event) {
if (event.type === 'picklistchanged'){
}
console.log('START--handleSave');
console.log('Updated items = ', this.draftValues);
// save last saved copy
this.lastSavedData = JSON.parse(JSON.stringify(this.data));
console.log('this.lastSavedData = ' + JSON.stringify(this.lastSavedData));
this.fldsItemValues = event.detail.draftValues;
console.log('this.fldsItemValues = ' + JSON.stringify(this.fldsItemValues));
const inputsItems = this.fldsItemValues.slice().map(draft => {
const fields = Object.assign({}, draft);
console.log('JSON.stringify() fields ' + JSON.stringify(fields));
return { fields };
});
// Show toast after successful update
const promises = inputsItems.map(recordInput => updateRecord(recordInput));
Promise.all(promises).then(res => {
this.dispatchEvent(
new ShowToastEvent({
title: 'Success',
message: 'Records Updated Successfully!!',
variant: 'success'
})
);
this.fldsItemValues = [];
return this.refresh();
}).catch(error => {
this.dispatchEvent(
new ShowToastEvent({
title: 'Error',
message: 'An Error Occured!!',
variant: 'error'
})
);
}).finally(() => {
// Clear draft values
this.draftValues = [];
});
// Refresh the window after successful save
//window.open('url','_self');
//document.location.reload(true);
//cmp.find("table-component-id").set("v.draftValues", null);
console.log('END--handleSave');
}
handleCancel(event) {
//remove draftValues & revert data changes
this.data = JSON.parse(JSON.stringify(this.lastSavedData));
this.draftValues = [];
}
async refresh() {
console.log('async refresh');
await refreshApex(this.data);
//this.connectedCallback();
}
}
customDatatableDemo.html
<template>
<lightning-card title="Invoicing" icon-name="custom:custom17">
<div class="slds-var-m-around_medium">
<template if:true={data}>
<c-custom-data-table
object-api-name="Payment__c"
key-field="Id"
data={data}
value=""
show-row-number-column
columns={columns}
onpicklistchanged={picklistChanged}
onvalueselect={handleSelection}
draft-values={draftValues}
oncellchange={handleCellChange}
onsave={handleSave}
oncancel={handleCancel}>
</c-custom-data-table>
<template if:true={data.error}></template>
</template>
</div>
</lightning-card>
<p>Selected value is: {value}</p>
</template>
customDataTable.js
import LightningDatatable from 'lightning/datatable';
//import the template so that it can be reused
import DatatablePicklistTemplate from './picklist-template.html';
import { loadStyle } from 'lightning/platformResourceLoader';
import CustomDataTableResource from '#salesforce/resourceUrl/CustomDataTable';
export default class CustomDataTable extends LightningDatatable {
static customTypes = {
picklist: {
template: DatatablePicklistTemplate,
typeAttributes: ['label', 'placeholder', 'options', 'value', 'context'],
},
};
constructor() {
super();
Promise.all([
loadStyle(this, CustomDataTableResource),
]).then(() => {})
}
}
picklist-template.html (Same folder as customDataTable)
<template>
<c-datatable-picklist label={typeAttributes.label} value={typeAttributes.value}
placeholder={typeAttributes.placeholder} options={typeAttributes.options} context={typeAttributes.context}>
</c-datatable-picklist>
</template>
datatablePicklist.js
import { LightningElement, api, track } from 'lwc';
export default class DatatablePicklist extends LightningElement {
#api label;
#api placeholder;
#api options;
#api value;
#api context;
handleChange(event) {
//show the selected value on UI
this.value = event.detail.value;
//fire event to send context and selected value to the data table
this.dispatchEvent(new CustomEvent('picklistchanged', {
composed: true,
bubbles: true,
cancelable: true,
detail: {
data: { context: this.context, value: this.value }
}
}));
}
}
datatablePicklist.html
<template>
<div class="picklist-container">
<lightning-combobox name="picklist" label={label} value={value} placeholder={placeholder} options={options}
onchange={handleChange}></lightning-combobox>}
</div>
</template>
lwcEditSaveRow.js
import { LightningElement, wire, track } from 'lwc';
import getAccounts from '#salesforce/apex/lwcEditSaveRowCtrl.getAccounts';
import { updateRecord } from 'lightning/uiRecordApi';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import { refreshApex } from '#salesforce/apex';
const columns = [
{
label: 'Name',
fieldName: 'Name',
type: 'text',
}, {
label: 'Phone',
fieldName: 'Phone',
type: 'phone',
editable: true,
}, {
label: 'Industry',
fieldName: 'Industry',
type: 'text',
editable: true,
}, {
label: 'Type',
fieldName: 'Type',
type: 'text',
editable: true
}, {
label: 'Description',
fieldName: 'Type',
type: 'text',
editable: true
}
];
export default class LwcEditSaveRow extends LightningElement {
columns = columns;
#track accObj;
fldsItemValues = [];
#wire(getAccounts)
cons(result) {
this.accObj = result;
if (result.error) {
this.accObj = undefined;
}
};
saveHandleAction(event) {
this.fldsItemValues = event.detail.draftValues;
const inputsItems = this.fldsItemValues.slice().map(draft => {
const fields = Object.assign({}, draft);
return { fields };
});
const promises = inputsItems.map(recordInput => updateRecord(recordInput));
Promise.all(promises).then(res => {
this.dispatchEvent(
new ShowToastEvent({
title: 'Success',
message: 'Records Updated Successfully!!',
variant: 'success'
})
);
this.fldsItemValues = [];
return this.refresh();
}).catch(error => {
this.dispatchEvent(
new ShowToastEvent({
title: 'Error',
message: 'An Error Occured!!',
variant: 'error'
})
);
}).finally(() => {
this.fldsItemValues = [];
});
}
async refresh() {
await refreshApex(this.accObj);
}
}
lwcEditSaveRow.html
<template>
<lightning-card>
<div class="slds-m-around_medium">
<h3 class="slds-text-heading_medium"><lightning-icon icon-name="custom:custom84" size="small"></lightning-icon> <strong style="color:#270086; font-size:13px; margin-right:5px;"> How to inline Edit/Save Rows With Lightning Datatable in Lightning Web Component (LWC) </strong></h3>
<br/><br/>
<template if:true={accObj.data}>
<lightning-datatable key-field="Id"
data={accObj.data}
columns={columns}
onsave={saveHandleAction}
draft-values={fldsItemValues}
hide-checkbox-column
show-row-number-column>
</lightning-datatable>
</template>
<br/>
<br/>
<!--Start RelatedTopics Section-->
<div style="border:1px #ddd solid; padding:10px; background:#eee; margin:40px 0;">
<p data-aura-rendered-by="435:0"><img src="https://www.w3web.net/wp-content/uploads/2021/05/thumbsUpLike.png" width="25" height="25" style="vertical-align:top; margin-right:10px;" data-aura-rendered-by="436:0"><strong data-aura-rendered-by="437:0"><span style="font-size:16px; font-style:italic; display:inline-block; margin-right:5px;">Don't forget to check out:-</span>An easy way to learn step-by-step online free Salesforce tutorial, To know more Click <span style="color:#ff8000; font-size:18px;" data-aura-rendered-by="442:0">Here..</span></strong></p>
<br/><br/>
<p data-aura-rendered-by="435:0"><img src="https://www.w3web.net/wp-content/uploads/2021/07/tickMarkIcon.png" width="25" height="25" style="vertical-align:top; margin-right:10px;" data-aura-rendered-by="436:0"><strong data-aura-rendered-by="437:0"><span style="font-size:17px; font-style:italic; display:inline-block; margin-right:5px; color:rgb(255 128 0);">You May Also Like →</span> </strong></p>
<div style="display:block; overflow:hidden;">
<div style="width: 50%; float:left; display:inline-block">
<ul style="list-style-type: square; font-size: 16px; margin: 0 0 0 54px; padding: 0;">
<li>How to get selected checkbox value in lwc</li>
<li>how to display account related contacts based on AccountId in lwc</li>
<li>how to create lightning datatable row actions in lwc</li>
<li>how to use if and else condition in lwc</li>
<li>how to display selected radio button value in lwc</li>
</ul>
</div>
<div style="width: 50%; float:left; display:inline-block">
<ul style="list-style-type: square; font-size: 16px; margin: 0 0 0 54px; padding: 0;">
<li>display account related contacts based on account name in lwc</li>
<li>how to insert a record of account Using apex class in LWC</li>
<li>how to get picklist values dynamically in lwc</li>
<li>how to edit/save row dynamically in lightning component</li>
<li>update parent field from child using apex trigger</li>
</ul>
</div>
<div style="clear:both;"></div>
<br/>
<div class="youtubeIcon">
<img src="https://www.w3web.net/wp-content/uploads/2021/11/youtubeIcon.png" width="25" height="25" style="vertical-align:top; margin-right:10px;"/> <strong>TechW3web:-</strong> To know more, Use this <span style="color: #ff8000; font-weight: bold;">Link</span>
</div>
</div>
</div>
<!--End RelatedTopics Section-->
</div>
</lightning-card>
</template>
Example of changing and saving non-picklist value in datatable:
Changing and saving non-picklist value
Example of changing and saving a picklist value:
Changing and saving picklist value (1)
Last bit of console output:
Changing and saving picklsit value (2)
As this is my first time working with Lightning Web components, I would greatly appreciate any assistance you may provide. Thanks in advance.
I was able to get this custom data table component working for something I am developing to effectively bind records as rows. Here 2 differences I notice:
I did not include onvalueselect and oncellchange methods for the component html declaration, only the onpicklistchanged.
You may want to use your custom server side controller method instead of the built-in uiRecordApi->updateRecord one. Something tells me this may not play nice with row data from the data table. In my implementation, I was simply able to pass the draftValues over to the server side method which has a single parameter of list of sObject:
async saveRecords(event){
const updatedFields = event.detail.draftValues;
this.draftValues = [];
this.showSpinner = true
try{
await saveRelatedRecords({sObjs: updatedFields}) // server side save
.then((result) => {
this.updateMessage = result;
})
this.showSpinner = false;
if(this.updateMessage == 'success'){
this.showToast('Success', 'Record(s) Updated', 'success');
} else{
this.showToast('Error', this.updateMessage, 'error');
}
await refreshApex(this._wiredRecordData);
this.unsavedData = this.records;
} catch (error) {
this.showSpinner = false;
this.showToast('Error while updating or refreshing records', error.body.message, 'error');
}
}
In regards to your data not refreshing, I suggest you wire your getPayments method so that you can always get a fresh set from the server side, rather than trying to keep track of and maintain data changes on the client side, something like:
_wiredRecordData;
#wire(getRelatedRecords)
relatedRecords(getRecsResult){
const { data, error } = getRecsResult;
this._wiredRecordData = getRecsResult;
if(data){
this.records = data;
}
}
Then after your success toast in your save method, you can use
await refreshApex(_wiredRecords); and lwc knows to rerender based on the wiring (or at least I think that's how it works.)
Lastly, here is the server side controller method I have to dynamically generate column header information so it does not need to be hard coded into the component. However I did need to modify the custom component a bit to include a new "fieldapi" attribute so that the client side method knows what field to set for the changed value during the onpicklistchanged action.
#AuraEnabled(cacheable=true)
public static String getColumnHeaders(String sObjAPI, String fieldAPIs)
{
List<ColumnHeaderInfo> colHeaders = new List<ColumnHeaderInfo>();
Schema.DescribeSObjectResult sObjDesc = Schema.getGlobalDescribe().get(sObjAPI).getDescribe();
Boolean objIsUpdateable = sObjDesc.isUpdateable();
Map<String, Schema.SObjectField> objFields = sObjDesc.fields.getMap();
for(String field: fieldAPIs.split(','))
{
if(!objFields.keySet().contains(field.toLowerCase())){
continue;
}
Schema.DescribeFieldResult fieldDesc = objFields.get(field).getDescribe();
if(!fieldDesc.isAccessible()){
continue;
}
ColumnHeaderInfo colHeader = new ColumnHeaderInfo();
colHeader.label = fieldDesc.getLabel();
colHeader.fieldName = fieldDesc.getName();
colHeader.editable = fieldDesc.isUpdateable() && sObjDesc.isUpdateable();
colHeader.type_x = fieldDesc.getType().name().toLowerCase();
if(colHeader.type_x == 'picklist')
{
colHeader.type_x = 'picklist';
List<Schema.PicklistEntry> picklistValues = fieldDesc.getPicklistValues();
colHeader.typeAttributes = new TypeAttributes();
colHeader.typeAttributes.options = new List<Option>();
for(Schema.PicklistEntry ple: picklistValues)
{
Option opt = new Option();
opt.value = ple.getValue();
opt.label = ple.getLabel();
colHeader.typeAttributes.options.add(opt);
}
colHeader.typeAttributes.context = new FieldName();
colHeader.typeAttributes.context.fieldName = 'Id';
colHeader.typeAttributes.value = new FieldName();
colHeader.typeAttributes.value.fieldName = fieldDesc.getName();
colHeader.typeAttributes.fieldapi = fieldDesc.getName();
}
// multi-select picklist fields not supported so make them read-only
if(colHeader.type_x == 'multipicklist'){
colHeader.editable = false;
}
colHeaders.add(colHeader);
}
return JSON.serialize(colHeaders).replaceAll('type_x', 'type');
}
private class ColumnHeaderInfo
{
public String label;
public String fieldName;
public String type_x;
public Boolean editable;
public TypeAttributes typeAttributes;
}
private class TypeAttributes
{
public String placeholder;
public List<Option> options;
public FieldName value;
public FieldName context;
public FieldName label;
public FieldName tooltip;
public String fieldapi;
public String target;
}
private class Option
{
public String label;
public String value;
}
private class FieldName
{
public String fieldName;
}
i am actually using graphs in my project for which i am passing dynamic data from controller to blade and then in the js script. The js function in the blade accept the array of objects and i dont know how to assign the data from the controller to that js function.
$data['typesBasedProperties'] = DB::table('properties')
->join('property_types', 'properties.property_type', 'property_types.id')
->select('property_types.types as label', DB::Raw('COUNT(properties.id) as value'))
->whereIn('properties.id', $property_ids)
->groupBy('label')
->get()
->toJson();
and this is the js function
var donutChart = function(){
Morris.Donut({
element: 'morris_donught',
data: [
{
label: " Download Sales ",
value: 12,
}, {
label: " In-Store Sales ",
value: 30
}, {
label: " Mail-Order Sales ",
value: 20
}
],
resize: true,
redraw: true,
colors: ['#2b98d6', 'rgb(59, 76, 184)', '#37d159'],
//responsive:true,
});
}
I think you need to do something like this:
<script>
var typesBasedProperties = {!! $typesBasedProperties !!}
</script>
After this you have typesBasedProperties object available in all your js code.
Check out laravel documentation for more info.
You can use ajax request to fetch data from laravel controller to javascript or JQuery.
here's some example
controller
function bbq(Request $r){
$data = DB::select('CALL bukubesar('.$r->no.')');
$node = DB::select('CALL infonode('.$r->no.')');
return array(
'data' => $data,
'node' => $node
);
}
route (I'm using Group)
Route::controller(CPembukuan::class)->group(function () {
Route::get ('/pembukuan-besar', 'bukubesar');
Route::get ('/pembukuan-besar/query', 'bbq' );
Route::get ('/pembukuan-labarugi', 'labarugi' );
Route::get ('/pembukuan-labarugi/query', 'lrq' );
});
ajax (JQuery) on html or blade file
//a variable to pass to controller (optional)
val = $('#kode').val();
$.ajax({
type: "get",
url: "/pembukuan-besar/query",
data: {
'no': val // the data represented as 'no'
},
success: function(data) {
console.log(data); // to view the data in console
//do anything you want here
}
});
I have some problem accessing to model attribute in Javascript; in particular I have this controller:
#RequestMapping(value = "/dashboard")
public ModelAndView home(HttpServletRequest request, HttpServletResponse
res, Model model) {
// Return answer's dictionary from DB to dashboard view
CompQuest dizRisp = new CompQuest();
dizRisp.setDizComp(dashDao.getRispEnd());
model.addAttribute("dizRisp", dizRisp);
return new ModelAndView("dashboard");
}
and I have this Javascript file (here: only the part with the code for my chart where I want to refer to model attribute) where I want to access to model attribute "dizRisp" from my controller:
var ctx1 = document.getElementById('myChart1').getContext('2d');
var myRadarChart = new Chart(ctx1, {
type: 'radar',
data: {
labels: ['Valori e identità del SCN', 'La cittadinanza attiva',
'Il giovane volontario nel sistema del SC', 'Lavorare',
'Prevenzione e protezione', 'Normativa sicurezza',
'Rischi sulla salute in tema di ambiente'
],
datasets: [{
label: "Civiche",
data: [4, 5, 5, 2, 4, 5, 4],
fill: true,
borderJoinStyle: "round"
}],
},
options: {
maintainAspectRatio: false,
scale: {
ticks: {
stepSize: 1,
step: 1,
beginAtZero: true,
max: 5
}
}
}
});
My classes are (here: no getters and setters):
public class CompQuest {
private HashMap <String, CompRisp> dizComp;}
public class CompRisp {
private ArrayList <Risposte> rispList = new ArrayList <Risposte> ();}
public class Risposte {
int id;
Domande domande;
int valore;
int momento; }
public class Domande {
int id;
String testo;
String descrizione;
Questionario questionario; }
My .jsp file:
<meta charset="UTF-8">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.4.0/Chart.min.js" ></script>
<script src="resources/dashboard.js" type="text/javascript"></script>
<link rel="stylesheet" href="${pageContext.request.contextPath}/resources/dashboard.css">
<title>Dashboard</title>
<style>
#import url('https://fonts.googleapis.com/css?family=Bitter|Roboto+Condensed');
#import url('https://fonts.googleapis.com/css?family=Roboto');
</style>
In particular I would want to access to my model attribute (Hashmap) in order to put in label and datasets field of my Javascript chart values from my Hashmap that contains data from my Database.
Thanks in advance to everyone that can help me!
Spring controller
#RequestMapping(value = "/dashboard")
public ModelAndView home(HttpServletRequest request,
HttpServletResponse
res, Model model) {
// Return answer's dictionary from DB to dashboard view
CompQuest dizRisp = new CompQuest();
dizRisp.setDizComp(dashDao.getRispEnd());
Gson gson = new Gson() ;
// Use Gson dependency to convert hashmap to String
String strmap = gson.toJson(dizRisp)
model.addAttribute("dizRisp", strmap);
return new ModelAndView("dashboard");
}
Javascript
<script>
$(document).ready(function(){
var element = JSON.parse('${dizRisp}');
$.each( element , function( key, value ) {
console.log(key);
console.log(value);
});
});
</script>
Hope this is what your trying to achieve.
I am trying to create a multiple choice list using Select2, Razor and the MVC framework. My problem is that the object in the controller that receives the array input is always null. The front-end looks as follows:
<form class="form-horizontal" method="post" action="#Url.Action(MVC.Configurazione.Contatori.Edit())">
<div class="form-group">
<div class="col-lg-8">
<select class="form-control attributoSelect2" name="attributiSelezionati" value="#Model.AttributiSelezionati">
<option value="#Model.AttributiSelezionati" selected>#Model.AttributoDescrizione</option>
</select>
</div>
</div>
</form>
The action method "Edit", is the controller method that receives the array of chosen items from the drop-down list.
The Javascript is the following:
$('.attributoSelect2').select2({
placeholder: "Search attribute",
multiple: true,
allowClear: true,
minimumInputLength: 0,
ajax: {
dataType: 'json',
delay: 150,
url: "#Url.Action(MVC.Configurazione.Attributi.SearchAttrubutes())",
data: function (params) {
return {
search: params.term
};
},
processResults: function (data) {
return {
results: data.map(function (item) {
return {
id: item.Id,
text: item.Description
};
})
};
}
}
});
And finally the C# controller has an object that is expected to retrieve the data from the view and is defined:
public string[] AttributiSelezionati { get; set; }
and the HttpPost method that receives the data is:
[HttpPost]
public virtual ActionResult Edit(EditViewModel model) { }
Could someone give me some insight into what I am doing wrong and the areas that I should change in order to find the problem?
you class name error not attributoSelect2 is attributesSelect2 , I also make this mistake often. haha
<select class="form-control attributoSelect2" name="attributiSelezionati" value="#Model.AttributiSelezionati">
<option value="#Model.AttributiSelezionati" selected>#Model.AttributoDescrizione</option>
</select>
There are multiple reason for not being receiving data on server. First of all you need to change your select code as follow
#Html.DropDownList("attributiSelezionati", Model.AttributiSelezionati, new { #class = "form-control attributo select2" })
now go to console in browser and get the data of element to confirm that your code properly works in HTML & JS
After that you need to add attribute at your controller's action method as
[OverrideAuthorization]
[HttpPost]
You can try the following approach that has been used in some of our projects without any problem:
View:
#Html.DropDownListFor(m => m.StudentId, Enumerable.Empty<SelectListItem>(), "Select")
$(document).ready(function () {
var student = $("#StudentId");
//for Select2 Options: https://select2.github.io/options.html
student.select2({
language: "tr",//don't forget to add language script (select2/js/i18n/tr.js)
minimumInputLength: 0, //for listing all records > set 0
maximumInputLength: 20, //only allow terms up to 20 characters long
multiple: false,
placeholder: "Select",
allowClear: true,
tags: false, //prevent free text entry
width: "100%",
ajax: {
url: '/Grade/StudentLookup',
dataType: 'json',
delay: 250,
data: function (params) {
return {
query: params.term, //search term
page: params.page
};
},
processResults: function (data, page) {
var newData = [];
$.each(data, function (index, item) {
newData.push({
//id part present in data
id: item.Id,
//string to be displayed
text: item.Name + " " + item.Surname
});
});
return { results: newData };
},
cache: true
},
escapeMarkup: function (markup) { return markup; }
});
//You can simply listen to the select2:select event to get the selected item
student.on('select2:select', onSelect)
function onSelect(evt) {
console.log($(this).val());
}
//Event example for close event
student.on('select2:close', onClose)
function onClose(evt) {
console.log('Closed…');
}
});
Controller:
public ActionResult StudentLookup(string query)
{
var students = repository.Students.Select(m => new StudentViewModel
{
Id = m.Id,
Name = m.Name,
Surname = m.Surname
})
//if "query" is null, get all records
.Where(m => string.IsNullOrEmpty(query) || m.Name.StartsWith(query))
.OrderBy(m => m.Name);
return Json(students, JsonRequestBehavior.AllowGet);
}
Hope this helps...
Update:
Dropdown option groups:
<select>
<optgroup label="Group Name">
<option>Nested option</option>
</optgroup>
</select>
For more information have a look at https://select2.org/options.
So yesterday I started learning javascript and web development for a project at work. We are using a MVC pattern and I am having issues figuring out exactly how the javascript classes work with the views. Any help on this will be appreciated. Like I said, my knowledge is very limited. I do, however, know C# and WPF (MVVM) so maybe some of that knowledge will help me here.
We use Kendo controls. Some of the javascript for our kendo grid is below.
grid.js:
function onChange(e) {
//get currently selected dataItem
var grid = e.sender;
var selectedRow = grid.select();
var dataItem = grid.dataItem(selectedRow);
var y = $.ajax({
url: "/api/ServiceOrderData/" + dataItem.id,
type: 'GET',
dataType: 'json'
});
}
$("#serviceOrderList").kendoGrid({
groupable: true,
scrollable: true,
change: onChange,
sortable: true,
selectable: "row",
resizable: true,
pageable: true,
height: 420,
columns: [
{ field: 'PriorityCodeName', title: ' ', width: 50 },
{ field: 'ServiceOrderNumber', title: 'SO#' },
{ field: 'ServiceOrderTypeName', title: 'Type' },
{ field: 'ScheduledDate', title: 'Scheduled Date' },
{ field: 'StreetNumber', title: 'ST#', width: '11%' },
{ field: 'StreetName', title: 'Street Name' },
{ field: 'City', title: 'City' },
{ field: 'State', title: 'ST.' },
{ field: 'IsClaimed', title: 'Claimed'}
],
dataSource: serviceOrderListDataSource
});
I am wanting to be able to use the value from the onChange function:
var dataItem = grid.dataItem(selectedRow);
in the following view.
ESRIMapView.cshtml:
<body class="claro">
<div id="mainWindow" data-dojo-type="dijit/layout/BorderContainer"
data-dojo-props="design:'sidebar', gutters:false"
style="width:100%; height:100%;">
<div id="leftPane"
data-dojo-type="dijit/layout/ContentPane"
data-dojo-props="region:'left'">
<br>
<textarea type="text" id="address" />*THIS IS WHERE I WILL USE dataItem! dataItem.StreetNumber (syntax?) to be exact</textArea>
<br>
<button id="locate" data-dojo-type="dijit/form/Button">Locate</button>
</div>
<div id="map"
data-dojo-type="dijit/layout/ContentPane"
data-dojo-props="region:'center'">
</div>
</div>
</body>
Right now my ESRIMapView is loaded when the user clicks on a button on the index.cshtml screen which contains the grid that I am trying to get the value from.
<li>#Html.ActionLink("Map", "ESRIMapView", "Home", null, new { #class = "k-button" })</li>
This is my "Home" controller:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Services.Description;
using Alliance.MFS.Data.Client.Models;
using Alliance.MFS.Data.Local.Repositories;
namespace AllianceMobileWeb.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.Message = "Welcome to ASP.NET MVC!";
return View();
}
public ActionResult About()
{
ViewBag.Message = "Your app description page.";
return View();
}
public ActionResult ServiceOrderMaintenance()
{
ViewBag.Message = "Your contact page.";
return View();
}
public ActionResult ESRIMapView()
{
ViewBag.Message = "Your contact page.";
return View();
}
}
}
I realize this is probably a very elementary question, but any help would be appreciate. And please be as detailed as possible with your responses :)
Since you create your link before returning the (initial) view to the user, you need a bit of trickery to change it. I recommend the following: set an id on your a element and change its href attribute; on your controller, set a parameter corresponding to the street number and pre-fill the view:
Controller:
public ActionResult ESRIMapView(string streetNumber)
{
ViewBag.Message = "Your contact page.";
ViewBag.StreetNumber = streetNumber;
return View();
}
View containing the li (note the Id on the a element):
<li>#Html.ActionLink("Map", "ESRIMapView", "Home", null, new { #class = "k-button", id="myMapaction" })</li>
View containing the textarea (ESRIMapView ):
<textarea type="text" id="address" />#ViewBag.StreetNumber</textArea>
grid.js:
function onChange(e) {
//get currently selected dataItem
var grid = e.sender;
var selectedRow = grid.select();
var dataItem = grid.dataItem(selectedRow);
//change the link
var actionElem = $("#myMapaction");
var url = actionElem.attr("href");
if (url.indexOf("=") === -1) { //first time selecting a row
url += "?streetNumber=" + dataItem.StreetNumber;
} else {
url = url.substring(0, url.lastIndexOf("=") +1) + dataItem.StreetNumber;
}
actionElem.attr("href", url);
//change the link
var y = $.ajax({
url: "/api/ServiceOrderData/" + dataItem.id,
type: 'GET',
dataType: 'json'
});
}
This script simply adds the street number parameter in the query string. When the user selects a row for the first time, the streetNumber parameter is not present in the query string. After the first time, the parameter is there and we must change only the value.
Please note that this solution has its limitations: it does not work if you have other parameters in the query string (the logic for adding/editing the parameter must be changed).