I'm using the Obout.com MVC controls and have included the following code in one of my views:
#{
Html.Obout(new ComboBox("Languages") {
Width = 175,
SelectedIndex = (int) ViewData["DefaultLanguage"] - 1,
ShowSelectedImage = true
}
);
}
I'm doing it that way because my original attempt failed:
#Html.Obout(new ComboBox("Languages") { Width = 175, SelectedIndex = (int) ViewData["DefaultLanguage"] - 1, ShowSelectedImage = true })
...it seems I need to use the #{} structure. However, when the output gets generated, the code that Html.Obout() generates comes ahead of all other output. the <!DOCTYPE html> and the real page follows the control's output. is this a function of the #{} structure, or is it some issue with the control itself?
It looks like this method was designed for ASPX views and writes directly to HttpContextBase.Response.OutputStream.
Since Razor buffers its output in WebPageBase.Output, you will not easily be able to use these helpers in Razor.
You could put them in a separate ASCX partial view, and they will work.
Depending on how the helpers are implemented, you may be able to force them to write to WebPageBase.Output; since I don't use Obout, I don't know.
The Razor compatible version of the Obout MVC ComboBox will be available soon:
http://forum.obout.com/yaf_postsm2112_Examples-pleease.aspx#post2112
Related
I'm working on a Kendo Mobile project with a number of:
Kendo Views (external to root html)
Modal Views (in the root html).
The external files load on demand and everything works fine. But i'd like to have the same load on demand behavior for some of the modal views, because the root/based html file is becoming too large and not manageable.
Is there a way to either:
Store a modal view in an external file? If so is it possible to load via javascript syntax (app.navigate()) rather than the declarative syntax (href='externalmodal').
Manually pre-load an external view without navigating to it first.
This code lets you manually create a view:
var viewUrl = 'blahblahblah';
var element = $.parseHTML('<div data-role=view>test</div>')[0];
element.style.display = 'none';
$(document.body).append(element);
var options = $.extend({}, kendo.parseOptions(element, kendo.mobile.ui.View.fn.options));
var view = new kendo.mobile.ui.View(element, options);
view.element[0].setAttribute('data-url', viewUrl);
kendo.mobile.application.navigate(viewUrl, '');
Depending on what features you use, you may need to instead use code similar that that used for ModalView below so that Kendo creates the subclass (changes: substitute View for ModalView, substitute view for modalview, add data-url, remove call to show(), maybe check that view not already created by checking for element with matching data-url). We haven't tested setting roles.view this way, but we did something similar while testing this stuff out and it worked.
Don't try settings the options - Kendo got confused (at least trying to set useNativeScrolling didn't work, also don't try setting the options object on the subclass unless you really know what you are doing).
Caveat: This was using browserHistory:false (which disables routing) when the kendo.mobile.Application was created. The technique should still work when using browser history if you use a valid url fragment (same as would be created by Kendo for the pushstate/hashchange url).
This is a also way to cleanly subclass kendo.mobile.ui.View that works well - although you must still use data-role=view even though your subclass is a "different" component. Note that you can't just use you cant use your own subclassed component with its own name like role=myview to subclass a view because there are hard-coded checks specifically for data-role=view in the kendo codebase. Same if you wish to subclass: layout modalview drawer splitview page (amongst other hard-coded kendo ui component names - search kendo code for kendo.roleSelector - ugly). e.g.
MyView = kendo.mobile.ui.View.extend({
init: function(element, options) {
kendo.mobile.ui.View.prototype.init.apply(this, arguments);
...
var myView = new MyView('<div data-role=view>test</div>');
Why it works: The relevant function in the Kendo source code is _findViewElement which does element = this.container.children("[" + attr("url") + "='" + urlPath + "']"); to see if the view already exists for a url, before creating a new one. A unique init function is always required as it ends up being the constructor function.
If you want to subclass a modalview, you need to do something different due to the way kendo works:
var MyModalView = kendo.mobile.ui.ModalView.extend({
html: '<div data-role=modalview style="width:90%;display:none;">Foobar</div>',
init: function() {
kendo.mobile.ui.ModalView.prototype.init.apply(this, arguments);
}
});
function makeModalView() {
$(document.body).append($.parseHTML(MyModalView.prototype.html));
var roles = $.extend({}, kendo.mobile.ui.roles);
roles.modalview = MyModalView;
var modalView = kendo.initWidget($(element), {}, roles);
modalView.open();
return modalView;
}
I need access to the ApplicationView from another view and I'm able to do so with App.__container__.lookup('view:application').
Is __container__ intended to be used this way?
Is there a better way to access instances of views?
(update)
My usecase:
My ApplicationView has a template with 2 columns.
The CSS is responsive so the size of the columns changes to accommodate the
width of the page.
I'm using Ember List View which requires height and width to be specified during initialization
I want to get the instance so I can access the DOM object to figure out its size
I can't use Ember.View.views because at that point, the ApplicationView has not been inserted into the DOM
Don't use that. One of the core developers said that whenever someone tries to use App.__container__, he would add another underscore.
If you really want to access an Ember.View intance use Ember.View.views['foo']. Where foo is the elementId of the view instance.
So if for example you want the App.ApplicationView instance:
App.ApplicationView = Ember.View.extend({
elementId: 'application'
});
// somewhere else in your code
var applicationViewInstance = Ember.View.views['application'];
Having said that, I never came across a situation where I needed to access view instances like that. If you can post your use case, I may be able to suggest alternative ways.
UPDATE: You want to access some properties of a view instance, from some other view instance (view height and width). You can pass those properties to the controller and let other controllers access them for using them in other views (source view -> source controller -> some other controller -> some other view):
App.ApplicationView = Ember.View.extend({
didInsertElement: function() {
var controller = this.get('controller'),
height = this.$().height(),
width = this.$().width();
controller.setProperties({
height: height,
width: width
});
}
});
App.SomeotherController = Ember.Controller.extend({
needs: ['application'],
applicationViewWidthBinding: 'controllers.application.width',
applicationViewHeightBinding: 'controllers.application.height'
});
App.SomeOtherView = Ember.View.extend({
// assuming its controller is an instance of App.SomeotherController
applicationViewWidthBinding: 'controller.applicationViewWidth',
applicationViewHeightBinding: 'controller.applicationViewHeight'
});
I'm using Knockout MVC im my project (ASP.NET MVC3, Razor). I can't find now to change decimal format. I want to use comma as a decimal separator. When I bind data using non-knockout Razor helper, it renders it correctly (with comma), but when I bind using Knockout binding it renders the number with the dot as comma separator.
How to change the decimal format that is would use comma?
You're looking at the differences between your server and client locale.
Your .NET code formats numbers with respect to the server locale whereas your JS code formats numbers with respect to the browsers locale.
Try changing the locale/region within your browser.
EDIT:
(I am leaving the above in case it helps anyone else, even though it did not help you)
The issue is your understanding of the differences between server-side and client-side.
Razor code is executed on the server and 'translated' into HTML.
Whereas, the server treats Javascript as text and just part of the HTML document it is sending.
Javascript is executed on the clients machine (i.e. the browser).
How the Razor Helper formats the number is based on the locale set on the server. Whereas, the javascript will format the number based on the locale set in the browser.
To force Knockout/Javascript to format the number how you want regardless of the locale (on the client-side), you can write a custom-binding using the following method at it's core:
function formatWithComma(x, precision, seperator) {
var options = {
precision: precision || 2,
seperator: seperator || ','
}
var formatted = x.toFixed( options.precision );
var regex = new RegExp('^(\\d+)[^\\d](\\d{' + options.precision + '})$');
formatted = formatted.replace(regex, '$1' + options.seperator + '$2');
return formatted;
}
So your binding will look something like this:
ko.bindingHandlers.commaDecimalFormatter = {
init: function(element, valueAccessor) {
var observable = valueAccessor();
var interceptor = ko.computed(function() {
return formatWithComma( observable() );
}
ko.applyBindingsToNode( element , { value: interceptor } );
}
}
And then in your Razor view:
#ko.Bind.Custom("commaDecimalFormatter ", m => m.MyCustom)
(Please note, I've never used KnockoutMVC and so this last line is straight from the documentation with the binding name changed - it is untested.
Also, I have used a ko.computed and so this binding is read-only - using it on an <input> element will be pointless. It's better used on a <span>. You can make this a two-way binding implementing the reverse:
ko.computed( {
read: function() {
/* method as above */
},
write: function(newValue) {
/* implement reverse */
observable( newValue );
}
}
EDIT 2
Hope this fiddle makes it clearer
Trying to put some pieces together here.
Piece 1: I know that I can get the current username in MVC by using:
#HttpContext.Current.User.Identity.Name
in my razor view.
Piece 2: I have some MVVM-style code in a separate JS file, relevant parts shown below:
var FeedbackViewModel = function () {
var self = this;
self.username = ko.observable("");
self.feedbackText = ko.observable("");
self.userNameCaptured = ko.computed(function () { return self.username().length > 3; }, self);
};
var feedbackViewModel = new FeedbackViewModel();
ko.applyBindings(feedbackViewModel, document.getElementById("feedbackModal"));
Question: How do I pass the current username from MVC3 to the Knockout viewModel so that I can observe and take action based upon it?
I assume feedbackViewModel is defined as a global variable, so you could simply add some code to the CSHTML file to populate it inline:
<script type="text/javascript">
feedbackViewmodel.username("#HttpContext.Current.User.Identity.Name");
</script>
Another option would be to pass the variable into the ViewModel function as a constructor element.
(I'd rather post this as comment than answer but somehow don't have option here)
I've faced similar problems in the past (handoff between razor and javascript). The best answer I've found is to create a hidden control (#hiddenval or #username) which can then be "read" by a JQuery selector.
This approach works for me every time. It's inelegant and may potentially expose info to a user sourcing the html...
if it's not obvious, #HttpContext.Current.User.Identity.Name should be populated as part of the markup
I guess it's a view within a view, but I'd rather it happen automatically. Any help?
Templates, or layouts as they are often called in various MVC frameworks, can be achieved a number of ways in CodeIgniter, but ultimately in any case, you're placing views within views (although it's bad practice to call a view directly from within another view).
One way to achieve this would be to load your internal views into an array, then pass that array into your layout view:
// Get ID From Segment
$id = $this->uri->segment(2);
// Get Article Data
$this->load->model('article');
$article = $this->article->getArticle($id);
// Define Layout View(s)
$layout['title'] = $article->title;
$layout['keywords'] = $article->keywords;
$layout['description'] = $article->description;
$layout['content'] = $this->load->view('articles/detail',array(
'body' => $article->body;
),true);
// Render Layout
$this->load->view('layouts/default',$layout);