How to refresh a viewcomponent asp.net core - asp.net-core-2.0

i have a view with 3 combo boxes that get their options from a database. when an option in one of them is selected, the others may have to be filtered. im making the call to my controller with ajax:
$(".dropFilter").on('change', function () {
var data = {
'EventEmitter': $(this).attr("id"),
'SelectedValue': $(this).val()
}
$.ajax({
type: 'POST',
url: '../MyController/FilterCombos',
dataType: 'json',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify(data),
success: function (msg) {
console.log(msg)
},
fail: function (msg) {
console.log(msg)
},
});
});
the controller method being called is the following:
[HttpPost]
public IActionResult FilterCombos([FromBody]FilterComboRequest fcr)
{
switch (fcr.EventEmitter)
{
case "combo1-dropdown":
return ViewComponent("MyViewComponent", new
{
firstFilter = fcr.SelectedValue,
secondFilter = 0,
thirdFilter = fcr.SelectedValue
});
case "combo2-dropdown":
return ViewComponent("MyViewComponent", new
{
firstFilter = 0,
secondFilter = fcr.SelectedValue,
thirdFilter = 0
});
}
return ViewComponent("MyViewComponent", new
{
firstFilter = 0,
secondFilter = 0,
thirdFilter = 0
});
}
my viewcomponent invokeAsync method is the following:
public async Task<IViewComponentResult> InvokeAsync(int firstFilter,int secondFilter,int thirdFilter)
{
var mOpciones = new MOpciones();
var lOpciones = new LOpciones(_config);
lOpciones.fill(mOpciones,firstFilter,secondFilter,thirdFilter);
return View(mOpciones);
}
the combos are filled like so:
#Html.DropDownList("combo1",
new SelectList(Model.First,"Id","Nombre"),
"",
new { #class = "col-6 form-control form-control-lg",
#id="combo1-dropdown" })
when debugging, i see that mOpciones is being filled correctly in InvokeAsync, and Model.First has the right options in Default.cshtml, but the view on the browser never changes. what am i doing wrong?

Feel drop-down values can be updated within Ajax call method in JS.
Example:
success: function (data) {
$.each(data, function (index, value) {
$("#Dropdown").append('<option value="'
+ value.Value + '">'
+ value.Value + '</option>');
});

Related

Why is displayStart (Datatable 1.10) not working for me?

I am using Datable (1.10.3) and whatever value I set in the diplayStart field, the start parameter of the server request always goes as 0.
Here is my code:
this.table = $('#table').DataTable({
displayStart: 100,
order: [[0, 'desc']],
processing: true,
serverSide: true,
searching: true,
pageLength: 50,
searchDelay: 1000,
language: {
lengthMenu: 'Show _MENU_ records per page'
},
dom: '<"top"il>rt<"bottom"p><"clear">',
ajax: {
url: <url>,
type: 'POST',
headers: {
authorization: <token>
},
data: function (d) {
//setting request data
},
dataSrc: (json) =>{
return json.data;
},
error: function (xhr, error, thrown) {
if (xhr.status + '' === '401') {
location.href = '/';
}
}
},
columns: this.getColumns(),
drawCallback: function () {
//some operations
}
});
It seems to work fine if I initialise the table like the older version, like this:
this.table = $('#table').dataTable({...
But this initialisation breaks other preexisting function calls (like search and row) in the code.
Can anyone suggest where I am going wrong and how can I fix this?
I am not sure if displayStart works with server side.
I realize this is not an ideal solution if you dont find any other you can override the pipeline method forcing it to use whatever you want:
$.fn.dataTable.pipeline = function ( opts ) {
return function ( request, drawCallback, settings ) {
request.start = 20;
return $.ajax( {
"type": opts.method,
"url": opts.url,
"data": request,
"dataType": "json",
"success": drawCallback
} );
}
};
Taken the example from: https://datatables.net/examples/server_side/pipeline.html

Displaying Block and floor and Room on single page using asp.net mvc

I am a beginner in asp.net MVC
I have tblBlock,tblFloor,tblRoom table in my database. I want to display all these in a single page like when I click Block number it should show the list of the floor and when I click on floor number it should show the number of rooms. how to do this within a single page in asp.net MVC.
This my view code
function GetFloors() {
$("#tblFloor tbody tr").remove();
console.log("Hello Javascript");
$.ajax({
type: "GET",
//url: "/RoomBooking/GetFloors",
url: '#Url.Action("GetFloors","RoomBooking")',
dataType: "json",
//cache: false,
async: "false",
contenttype:"charset=utf-8",
success: function (data) {
$.each(data, function (i, item) {
var rows = ""
+ ""
+ ' tblFloor ' + item.Floor_No + ""
+ "";
$('#tblFloor tbody').append(rows);
});
},
});
//Prevent default behavior
return false;
}
This is my controller
[HttpGet]
public JsonResult GetFloors()
{
List<tblFloor> floors = new List<tblFloor>();
floors = BlockRepsitory.GetFloors(1).ToList();
return Json(floors, JsonRequestBehavior.AllowGet);
}
Finally, I got a solution to this problem below is code for that solution:
<script>
$(document).ready(function () {
loadData();
});
function loadData() {
$.ajax({
url: "/PeopleBooking/Blocklist",
type: "GET",
contentType: "application/json;charset=utf-8",
dataType: "json",
success: function (result) {
var html = '';
$.each(result, function (key, item) {
html += '<div class="col-md-3 col-lg-3 col-xl-2 "><section class="panel panel-featured-left panel-featured-primary "><div class="panel-body zoom"><div class="widget-summary"><div class="widget-summary-col widget-summary-col-icon"><div class="summary-icon bg-white"><img src="/assets/images/RoomImg/block.png" width = "150" height = "150" class="img-circle img-responsive"/></div></div><div class="widget-summary-col"><div class="summary"><h4 class="title">' + item.Block_name + '</h4><div class="info"><strong class="amount">' + item.Block_No + '</strong></div></div></div></div></div></div></section></div>';
});
$('#yes').html(html);
},
error: function (errormessage) {
alert(errormessage.responseText);
}
});
}
</script>

How to manipulate the data of a query via JSON?

I'm using a third-party API (so far so good, I get the result), however as I'm new I'm having difficulty manipulating these results for the frontend (EJS)** ...
What the system should do is:
The site is a graphics panel, where I use the third-party API (it blocks the origin if consumed by the frontend) and I populate the data received in JSON, using the graphics plugin called (CHARTJS) .. The problem is there, because the API should be consumed as soon as the page is accessed and the graphics populated after consumption, but for me to consume this JSON I need to pass some QS ... These QSs when accessing the page for the first graphic are already automatic and can be manipulated by the form that contains the same page, in order to be able to carry out other queries ..
I am totally, lost, I would love some help and explanation ..
CONTROLLERS/LOGIN/LOGIN.JS
module.exports.index = (_application, _request, _response) => {
_response.render('login/index');
}
module.exports.check_login = (_application, _request, _response) => {
const JSON_MODEL = new _application.app.models.jsonDAO('fatVenda.xsjs', '\'BSC\'', '201807', 'vendaabs,vendam2');
JSON_MODEL.request();
console.log(JSON_MODEL.jsonData)
const VENDA_MODEL = new _application.app.models.vendaDAO('', '', '', '');
_response.render('home/home');
}
ROUTES/LOGIN/LOGIN.JS
module.exports = (_application) => {
_application.get('/login', (_request, _response) => {
_application.app.controllers.login.login.index(_application, _request, _response);
});
_application.post('/check_login', (_request, _response) => {
_application.app.controllers.login.login.check_login(_application, _request, _response);
});
}
MODELS/JSONDAO.JS
const REQUEST = require('request');
class JsonRequestDAO {
constructor(_xjs, _shoppingID, _periodUntil, _kpi){
this.xjs = _xjs;
this.shoppingID = _shoppingID;
this.periodUntil = _periodUntil;
this.kpi = _kpi;
}
request(){
REQUEST.get({
uri: `URL${this.xjs}`,
json: true,
qs: {
Shop: this.shoppingID,
PeriodoAte: this.periodUntil,
Kpi: this.kpi
},
headers: {
Authorization: 'Basic KEY',
ApiKey: 'KEY',
'Cache-Control': 'no-cache',
'Content-Type': 'application/json',
}
}, (_error, _response) => {
(_response.statusCode == 200) ? _response.body : console.log(_error);
});
}
}
module.exports = () => { return JsonRequestDAO; }
MODELS/VENDADAO.JS
class VendaDAO {
constructor(_shoppingName, _yearMonth, _competence, _sale, _salePercentage, _saleSquareMeter, _salePercentageSquareMeter){
this.shoppingName = _shoppingName;
this.yearMonth = _yearMonth;
this.competence = _competence;
this.sale = _sale;
this.salePercentage = _salePercentage;
this.saleSquareMeter = _saleSquareMeter;
this.salePercentageSquareMeter = _salePercentageSquareMeter;
}
static get shoppingName() { return this.shoppingName; }
static get yearMonth() { return this.yearMonth; }
static get competence() { return this.competence; }
static get sale() { return this.sale; }
static get salePercentage() { return this.salePercentage; }
static get saleSquareMeter() { return this.saleSquareMeter; }
static get salePercentageSquareMeter() { return this.salePercentageSquareMeter; }
}
module.exports = () => {
return VendaDAO;
}

How to return a PartialView from Core 2 RazorPage ViewModel Handler

In Asp.Net MVC, you can easily return a partial view by doing the following:
return PartialView("ModelName", Model);
How is this done on a RazorPage ViewModel Handler?
I figured this out. It is not nearly as straight forward as it is in MVC. You have to create an empty ViewDataDictionary() and then set its Model property to the partial's populated model.
View Model / Handler
public async Task<IActionResult> OnGetAsyncUpdateSearchResults(DateTime startDate, DateTime endDate, string selectedTypes)
{
int[] types = selectedTypes.Split(",").Select(x => int.Parse(x)).ToArray();
var inventory = await _itemService.GetFiltered(types, null, null, null, null, null, null, startDate, endDate.ToUniversalTime(), null, null, null, null, null, null, null);
if (inventory != null)
{
SearchResultsGridPartialModel = new SearchResultsGridPartialModel();
SearchResultsGridPartialModel.TotalCount = inventory.TotalCount;
SearchResultsGridPartialModel.TotalPages = inventory.TotalPages;
SearchResultsGridPartialModel.PageNumber = inventory.PageNumber;
SearchResultsGridPartialModel.Items = inventory.Items;
}
var myViewData = new ViewDataDictionary(new Microsoft.AspNetCore.Mvc.ModelBinding.EmptyModelMetadataProvider(), new Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary()) { { "SearchResultsGridPartialModel", SearchResultsGridPartialModel } };
myViewData.Model = SearchResultsGridPartialModel;
PartialViewResult result = new PartialViewResult()
{
ViewName = "SearchResultsGridPartial",
ViewData = myViewData,
};
return result;
}
I can now call this handler via ajax GET and have it return the partial's HTML. I can then set the partial's div and the partial refreshes as expected.
Here is the AJAX call I'm making:
var jsonData = { "startDate": startDate, "endDate": endDate, "selectedTypes": selectedTypesAsString };
$.ajax({
type: 'GET',
url: "searchresults/?handler=AsyncUpdateSearchResults",
beforeSend: function (xhr) {
xhr.setRequestHeader("XSRF-TOKEN", $('input:hidden[name="__RequestVerificationToken"]').val());
},
contentType: 'application/json; charset=utf-8"',
data: jsonData,
success: function (result) {
$("#searchResultsGrid").html(result);
},
error: function (error) {
console.log(error);
}
});
Thanks alot to TechFisher for figuring it out, here is a bit cleaner example.
public IActionResult OnGetTestPartial()
{
return new PartialViewResult()
{
ViewName = "Test",
ViewData = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary())
{
Model = new TestPartialData { Data = "inputhere" },
}
};
}
Partial view in a file name "Test.cshtml" in the same folder as the above class.
#using YourNamespace
#model TestPartialData
<div>Hello, model value: #Model.Data</div>
Load it async with jquery
$("#someHtmlElementId").load("Your/Path/TestPartial");

populating menus from multiple collections

I'm new to backbone.js and express and I have been adapting Christophe Coenraets Wine Cellar REST API example application for my own project.
I am building a form that has several menus needing to be populated from multiple unrelated collections in mongodb.
I am able to populate one menu with one collection, but I have no idea how to get more than one collection to my form View.
Here are the files I am using to populate one menu. How do I expand this to populate two menus?
I suppose I could make a new View for every menu I want to populate - but that seems like overkill.
Can I combine two mongodb find() collections into one object, and list them separately on a page? If so, how?
thanks in advance!
/routes/modules.js contains:
exports.findAllModules = function(req, res) {
db.collection('modules', function(err, collection) {
collection.find().toArray(function(err, items) {
res.send(items);
});
});
};
/server.js contains:
app.get('/modules', module.findAllModules);
/public/js/main.js contains:
routes: {
"modules" : "list" }
...
list: function(page) {
var p = page ? parseInt(page, 10) : 1;
var moduleList = new ModuleCollection();
moduleList.fetch({success: function(){
console.log('in list function');
$("#content").html(new ModuleListView({model: moduleList, page: p}).el);
}});
this.headerView.selectMenuItem('home-menu');
},
...
utils.loadTemplate([
'ModuleListItemView' ], function() {
app = new AppRouter();
Backbone.history.start(); });
/public/models/models.js contains:
window.Module = Backbone.Model.extend({
urlRoot: "/modules",
idAttribute: "_id",
initialize: function () {
this.validators = {};
this.validators.name = function (value) {
return value.length > 0 ? {isValid: true} : {isValid: false, message: "You must enter a name"};
};
validateItem: function (key) {
return (this.validators[key]) ? this.validators[key](this.get(key)) : {isValid: true};
},
validateAll: function () {
var messages = {};
for (var key in this.validators) {
if(this.validators.hasOwnProperty(key)) {
var check = this.validators[key](this.get(key));
if (check.isValid === false) {
messages[key] = check.message;
}
}
}
return _.size(messages) > 0 ? {isValid: false, messages: messages} : {isValid: true};
},
defaults: {
_id: null,
name: ""
} });
window.ModuleCollection = Backbone.Collection.extend({
model: Module,
url: "/modules"
});
/public/js/views/modulelist.js contains:
window.ModuleListView = Backbone.View.extend({
initialize: function () {
this.render();
},
render: function () {
var modules = this.model.models;
$(this.el).html('<ul class="thumbnails"></ul>');
for (var i = 0; i < modules.length; i++) {
$('.thumbnails', this.el).append(new ModuleListItemView({model: modules[i]}).render().el);
}
return this;
} });
window.ModuleListItemView = Backbone.View.extend({
tagName: "li",
initialize: function () {
this.model.bind("change", this.render, this);
this.model.bind("destroy", this.close, this);
},
render: function () {
$(this.el).html(this.template(this.model.toJSON()));
return this;
} });
/public/tpl/ModuleListView.html contains:
Not entirely sure how your code works, but here are a few backbone tips.
If you wanna build a menu from a collection don't pass the collection as a model.
Instead of:
$("#content").html(new ModuleListView({model: moduleList, page: p}).el);
Use:
$("#content").empty().append(new ModuleListView({collection: moduleList, page: p}).el);
Instead of:
render: function () {
var modules = this.model.models;
$(this.el).html('<ul class="thumbnails"></ul>');
for (var i = 0; i < modules.length; i++) {
$('.thumbnails', this.el).append(new ModuleListItemView({model: modules[i]}).render().el);
}
return this;
}
Use:
render: function () {
this.$el.html('<ul class="thumbnails">');
this.collection.each(function(model) {
this.$('.thumbnails').append(new ModuleListItemView({model: model}).render().el);
}, this);
return this;
}
If you have no need in updating or deleting your models, it's enough to add the url path /modules only to the collection, for reading the initial modules.

Resources