Url passing in telerik asp.net mvc panel - asp.net-mvc-3

I m using Telerik Panel bar in mvc3, and i am facing a problem while passing Url??
can anyone please help me how can i pass Url in my view.

You need to bring controller/Action name dynamically in you model and create and pass the url
.Items(sub =>
{
for (int i = 0; i < Model.Count(); i++)
{
sub.Add().Text(Model.ElementAt(i).DisplayText)
.Url(Url.Action(Model.ElementAt(i).ActionName, Model.ElementAt(i).ControllerName, new { id = Model.ElementAt(i).IDParam }))
}});

If I understand your question correctly, I did something similiar to this using the PanelBar and Grid.In the panel bar, put a js function in the OnSelect event:
Html.Telerik().PanelBar()
.Name("PanelBar")
.ClientEvents(events =>
{
events.OnSelect("getEvent");
})
.Items(panelbar =>
{
panelbar.Add()
.Text("Header Text")
.Expanded(true)
.Items(item =>
{
item.Add()
.Text("Test1");
item.Add()
.Text("Test2");
});
}).Render();
In the getEvent function, assign a variable to each item and make an ajax post to an actionresult on your controller or something. In my case I just made the grid rebind.
function getEvent(e) {
panelItem = $(e.item).text();
if (panelItem == "Test1") {
var eventid1 = 1;
}
if (panelItem == "Test2") {
var eventid2 = 2;
}
//make ajax post here or something
$('#TheGrid').data('tGrid').rebind();
// $.ajax({
// url: '/Controller/Action',
// type: 'POST',
// data: {
// eventid1: eventid1,
// eventid2: eventid2,
// panelItem: panelItem
// }
// });
}
and in your controller make a conditional statement for the eventids and perform the action you want.
Hope this helps.

Related

How can I pass values loaded by ajax to components?

I'm passing a value as a parameter to a component.
<badge-button params="badge: oarBadge"></badge-button>
Here is the viewModel containing oarBadge:
function AppViewModel() {
var self = this;
self.oarBadge = ko.observable();
$.getJSON('/guy.json', function(data) {
var badge = new Badge('wood oar', data.badges.oar, false);
self.oarBadge(badge);
// self.oarBadge().has() returns true so the badge is being properly created with data
// returned by the ajax call
});
} // AppViewModel()
Here is the Badge constructor:
function Badge(name, has, active) {
var self = this;
self.name = ko.observable(name);
self.has = ko.observable(has);
self.active = ko.observable(active);
self.disabled = ko.computed(function() {
return self.has();
});
self.toggleActive = function() {
self.active(!self.active())
};
self.toggleHas = function() {
self.has(!self.has());
};
}
Here is the component's viewModel:
ko.components.register('badge-button', {
viewModel: function(params) {
var self = this;
self.badge = params.badge();
self.open = function() {
self.badge.toggleHas();
self.badge.toggleActive();
}
},
template:
'<img class="ui image" src="http://fakeimg.pl/300/" data-bind="click: open, css: { disabled: badge.disabled }" >'
});
When the page loads, I get an error telling me that badge is undefined.
Full example: https://gist.github.com/guyjacks/5a8763ff71f90e3fe8b4b153ed9a5283
Try setting a default object before the ajax call is completed, also you should assign the observable itself not the evaluation for the observable, so instead of doing this:
self.badge = params.badge();
You should do it like this:
self.badge = params.badge;
Otherwise your variable won't be updated once the ajax request is completed.
Here is a small example: https://jsfiddle.net/b0bdru1u/1/
Note: As far as I know the disable binding won't work in images

kendo ui datasource read method makes two requests

I have a grid with a datasource read method
this.editorGridConfig = {
dataSource: {
transport: {
read: options => {
this.getSummaryData().then(res => {
options.success(res.data);
});
}
}
getSummaryData() {
console.log('get summary data');
let url = 'myEndPoint';
return ajaxRequest(url);
}
The getSummaryData is been called successfully and returns an array of objects.
The problem is when the options.success(res.data) is called kendo makes a new request on the this.getSummaryData is called twice.
if you are using a kendo route then this is the issue.
router.navigate('/page/' + e.index);
fires read() inside pagination onChange() and dataSource.query()
Solution is :
var url = window.location.href;
var pagelessUrl = url.indexOf("/page/") === -1 ? url.length - 1 : url.indexOf("/page/");
window.history.pushState('page'+e.index, document.title, url.substring(0,pagelessUrl)+"/page/" + e.index);

ember model find query with params doesn't display on pagination

2I have an Ember app which connects to an api from where it gets articles. I make use of pagination to get 10 articles per request. This works. But now I wanted to add sorting to the request. I implemented this by using the extra parameter in the store.find.
However, for some reason if I use the 'return this.store.find('article', params);' instead of 'return this.store.find('article');' new articles (still requested and added correctly to the store!) in the getMore function are not beiing displayed or rendered. But when i remove the params parameter from store.find in model, it does work. What could be the case here?
templates/articles.hbs
<script type="text/x-handlebars" data-template-name="articles">
{{#each itemController="article"}}
<div class="item">
//...
</div>
{{/each}}
</script>
routes/articles.js
import Ember from 'ember';
export default Ember.Route.extend(Ember.UserApp.ProtectedRouteMixin, {
model: function(params) {
var params2 = {page: 1, per_page: 10, sort: params.sort};
return this.store.find('article', params2);
},
setupController: function(controller, model) {
controller.set('content', model);
},
actions:{
//...
},
getMore: function() {
// don't load new data if we already are
//if (this.get('loadingMore')) return;
//this.set('loadingMore', true);
var meta = this.store.metadataFor("article");
if (meta.hasmore) {
var controller = this.get('controller'),
nextPage = controller.get('page') + 1,
perPage = controller.get('perPage'),
sorting = controller.get('sort'),
items;
var params = {page: nextPage, per_page: perPage, sort: sorting};
this.store.findQuery('article', params).then(function (articles) {
controller.set('page', controller.get('page') + 1);
//this.set('loadingMore', false);
});
}
else{
$('#pagination_spinner').hide();
}
},
queryParamsDidChange: function() {
this.refresh();
}
}
});
controllers/articles.js
import Ember from 'ember';
var ArticlesController = Ember.ArrayController.extend({
itemController: 'article',
queryParams: ['sort'],
sort: 'rating',
page: 1,
perPage: 10
});
export default ArticlesController;
views/articles.js
import Ember from 'ember';
export default Ember.View.extend({
didInsertElement: function(){
//this.scheduleMasonry();
this.applyMasonry();
// we want to make sure 'this' inside `didScroll` refers
// to the IndexView, so we use jquery's `proxy` method to bind it
//this.applyMasonry();
$(window).on('scroll', $.proxy(this.didScroll, this));
},
willDestroyElement: function(){
this.destroyMasonry();
// have to use the same argument to `off` that we did to `on`
$(window).off('scroll', $.proxy(this.didScroll, this));
},
// this is called every time we scroll
didScroll: function(){
if (this.isScrolledToBottom()) {
$('#pagination_spinner').addClass('active');
this.get('controller').send('getMore');
}
},
scheduleMasonry: (function(){
Ember.run.scheduleOnce('afterRender', this, this.applyMasonry);
}).observes('controller.model.#each'), //TODO check
applyMasonry: function(){
$('#pagination_spinner').removeClass('active');
var $galleryContainer = $('#galleryContainer');
$galleryContainer.imagesLoaded(function() {
// check if masonry is initialized
var msnry = $galleryContainer.data('masonry');
if ( msnry ) {
msnry.reloadItems();
// disable transition
var transitionDuration = msnry.options.transitionDuration;
msnry.options.transitionDuration = 0;
msnry.layout();
// reset transition
msnry.options.transitionDuration = transitionDuration;
} else {
// init masonry
$galleryContainer.masonry({
itemSelector: '.item',
columnWidth: 0,
"isFitWidth": true
});
}
});
},
destroyMasonry: function(){
$('#galleryContainer').masonry('destroy');
},
// we check if we are at the bottom of the page
isScrolledToBottom: function(){
var distanceToViewportTop = (
$(document).height() - $(window).height());
var viewPortTop = $(document).scrollTop();
if (viewPortTop === 0) {
// if we are at the top of the page, don't do
// the infinite scroll thing
return false;
}
return (viewPortTop - distanceToViewportTop === 0);
}
});
nothing smart coming to my mind, but maybe it's that...
You've got the line:
if (meta.hasmore) {
in your getMore() function. Is this the case that you've got this meta field in one response and forgot in the other?

Update knockout viewmodel when uploading documents via ajax

I'm trying to use knockout for a view where I'm uploading documents and showing a list. For this I'm using jquery.form.js in order to upload them using ajax. I've changed that to use knockout and my viewmodel looks like this
var ViewModel = function (groups) {
var self = this;
self.groups = ko.observableArray(ko.utils.arrayMap(groups, function (group) {
return {
planName: ko.observable(group.Key),
documentList: ko.observableArray(ko.utils.arrayMap(group.Values, function (value) {
return {
document: ko.observable(new Document(value))
};
}))
};
}));
var options = {
dataType: 'json',
success: submissionSuccess
};
self.add = function () {
$('#addForm').ajaxSubmit(options);
return false;
};
function submissionSuccess(result) {
alert('success');
}
};
Having one Document function for doing the mapping. I'm stuck when receiving the Json data from the controller. The result is correct, a list of objects in the same format I'm receiving on first load but I don't know how to "refresh" the viewmodel to use this new list.
Don't know if using the ko mapping plugin would make it easier as I have never used it and don't even know if it's applicable for this.
The controller method, in case is relevant, is this (if something else neede let me know althoug won't have access to the code in the next hours)
[HttpPost]
public ActionResult AddDocument(AddDocumentViewModel viewModel)
{
var partyId = Utils.GetSessionPartyId();
if (viewModel.File.ContentLength > Utils.GetKBMaxFileSize * 1024)
ModelState.AddModelError("File", String.Format("The file exceeds the limit of {0} KB", Utils.GetKBMaxFileSize));
if (ModelState.IsValid)
{
_documentsManager.AddDocument(viewModel, partyId);
if (Request.IsAjaxRequest())
{
var vm = _displayBuilder.Build(partyId);
return Json(vm.Documents);
}
return RedirectToAction("Index");
}
var newViewModel = _createBuilder.Rebuild(viewModel, partyId);
return PartialView("_AddDocument", newViewModel);
}
Thanks
EDIT: I came up with this code which seems to work (this function is inside the ViewModel one
function submissionSuccess(result) {
self.groups(ko.utils.arrayMap(result, function (group) {
return {
planName: ko.observable(group.Key),
documentList: ko.utils.arrayMap(group.Values, function (value) {
return {
document: new Document(value)
};
})
};
}));
};
Are you sure the documentList and document need to be observables themselves ?
To update the list you can push to it as you'd do on a regular array.
You could try something like this:
function submissionSuccess(result) {
self.groups.removeAll();
$.each(result, function(index, value) {
var documentList = [];
$.each(value.Values, function(index, value) {
documentList.push(new Document(value));
});
var group = {
planName:value.Key,
documentList: documentList
};
self.groups.push(group);
});
};

JsonLogOn via https

I've just introduced SSL to my MVC website. I made the whole default AccountContorller use it. It works fine unless I'm currently on http page and try to log on with ajax (the logon action is vredirected to httpS). This popup logon window doesn't even show up.
For the controller a used a custom attribute:
public class RequireSSL : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext.ActionDescriptor.IsDefined(typeof(NoSSL), true) ||
filterContext.ActionDescriptor.IsDefined(typeof(OptionalSSL), true))
{
base.OnActionExecuting(filterContext);
return;
}
HttpRequestBase req = filterContext.HttpContext.Request;
HttpResponseBase res = filterContext.HttpContext.Response;
//Check if we're secure or not and if we're on the local box
if (!req.IsSecureConnection && (!req.IsLocal || Properties.Settings.Default.UseSSLForLocalRequests))
{
var builder = new UriBuilder(req.Url)
{
Scheme = Uri.UriSchemeHttps,
Port = Properties.Settings.Default.HttpsPort,
};
res.Redirect(builder.Uri.ToString());
}
base.OnActionExecuting(filterContext);
}
}
How can I make it work?
EDIT
The whole rest was generated by MVC. (Project with built in authentications)
That's the link.
#Html.ActionLink(#Labels.LogOn, "LogOn", "Account", routeValues: null, htmlAttributes: new { id = "logonLink", data_dialog_title = "Identification" })
JS somehow hooks into that link and performs ajax logon . Probably with this code: (JajaxLogin.js - also out of the box)
/// <reference path="jquery-1.6.2.js" />
/// <reference path="jquery.validate.js" />
$(function () {
// Cache for dialogs
var dialogs = {};
var getValidationSummaryErrors = function ($form) {
// We verify if we created it beforehand
var errorSummary = $form.data('validation-summary-errors');
if (!errorSummary) {
errorSummary = $('<div class="validation-summary-errors"><span>Please correct the errors and try again.</span><ul></ul></div>')
.insertBefore($form);
// Remember that we created it
$form.data('validation-summary-errors', errorSummary);
}
return errorSummary;
};
var formSubmitHandler = function (e) {
var $form = $(this);
// We check if jQuery.validator exists on the form
if (!$form.valid || $form.valid()) {
$.post($form.attr('action'), $form.serializeArray())
.done(function (json) {
json = json || {};
// In case of success, we redirect to the provided URL or the same page.
if (json.success) {
location = json.redirect || location.href;
} else if (json.errors) {
var errorSummary = getValidationSummaryErrors($form);
var items = $.map(json.errors, function (error) {
return '<li>' + error + '</li>';
}).join('');
var ul = errorSummary
.find('ul')
.empty()
.append(items);
}
});
}
// Prevent the normal behavior since we opened the dialog
e.preventDefault();
};
var loadAndShowDialog = function (id, link, url) {
var separator = url.indexOf('?') >= 0 ? '&' : '?';
// Save an empty jQuery in our cache for now.
dialogs[id] = $();
// Load the dialog with the content=1 QueryString in order to get a PartialView
$.get(url + separator + 'content=1')
.done(function (content) {
dialogs[id] = $('<div class="modal-popup">' + content + '</div>')
.hide() // Hide the dialog for now so we prevent flicker
.appendTo(document.body)
.filter('div') // Filter for the div tag only, script tags could surface
.dialog({ // Create the jQuery UI dialog
title: link.data('dialog-title'),
modal: true,
resizable: true,
draggable: true,
width: link.data('dialog-width') || 300
})
.find('form') // Attach logic on forms
.submit(formSubmitHandler)
.end();
});
};
// List of link ids to have an ajax dialog
var links = ['logonLink', 'registerLink'];
$.each(links, function (i, id) {
$('#' + id).click(function (e) {
var link = $(this),
url = link.attr('href');
if (!dialogs[id]) {
loadAndShowDialog(id, link, url);
} else {
dialogs[id].dialog('open');
}
// Prevent the normal behavior since we use a dialog
e.preventDefault();
});
});
});

Resources