Using MVC 4, I am trying to send a viewmodel back to the controller with a value that was populated using Knockout in the javascript part section of my view.
Psuedocode:
var ProgramOptionsVm = function() {
self = this;
self.AvailableOptions is populated (IList<RegistrationOption>)
}
I want to set AvailableOptions equal to field of viewmodel. Something like:
Model.AvailableOptions = ProgramOptionsVm.AvailableOptions
Any advice would be great!
You can't set Model.AvailableOptions directly with your Knockout view model. The two things exist in different scopes: the former is server-side, while the latter is client-side. You would have to POST the data back to another controller action.
Related
Im curious, is there a proper way that one should handle/implement 2 way data binding between 2 nested controllers. Let me explain the scenario.
I have a formController in which has some form elements. One of the form elements is a multiselect widget, for which i created a partial html that i can use in other places, and this partial runs with a separate Controller, lets calle it multiSelectController (note, this controller/partial/view is nested within the form/formController).
What i want is to be able to have the formController (which has the data), to pass in a list of "selected" items, like [1, 3, 7, 10] to the multiselect partial, which will then be able to render the widget with the correct items selected. And at the same time, when an item gets deselected or selected from the multiselect partial, i want to be able to pass the new selected list to the formController/scope (so i can display saying 1, 3, 5 are now selected).
So to simplify the question, i want to know what is the best/corerct way to pass in a model/variable to a child view/controller while retaining the databinding, thus the child view/controller can make changes to the said variable within it while it updates the parent.
The best way according to me is :
Create a service, that will hold all the model variables.
angular.service("dataService", function() {
this.value1 = "";
this.value2 = "";
});
reference that service in your controllers, saving their reference in the scope.
angular.controller("myCntrl1", function($scope, dataService) {
$scope.dataService = dataService;
});
angular.controller("myCntrl2", function($scope, dataService) {
$scope.dataService = dataService;
});
Now in your html, you refer all your modal variables using the service reference :
// Controller 1 view
<div ng-controller="myCntrl1">
<input type="text" ng-model="dataService.value1" />
</div>
// Controller 2 view
<div ng-controller="myCntrl2">
The value entered by user is {{dataService.value1}}
</div>
Since formController is a parent controller, you need not worry about accessing its model/varaibales, just add $parent in child's scope to access any parent property
$scope.$parent.someProperty
So, if you change or update this variable, it will automatically updated in parent's scope also.
I am trying to retrieve the underlying model object from a controller so that it can be persisted (I am not using ember-data). The obvious way would simply be:
controller.get('content');
But this doesn't work. The problem can be summed up as follows:
controller.set("content", model);
sets the content as expected and at this point
controller.get('content');
works as expected. But if I then decorate the controller with other properties eg.
controller.set('IamNotPartOfTheModel', false);
then suddenly the 'content' includes this new property. I would've expected the content to remain unchanged and the new property to only be applied to the controller itself. I understand the controller is a proxy for the model so for the most part they are treated as one and the same but surely they should still be separable when needed? The whole point of this pattern is to separate data that should be stored from data that is just temporary. Am I missing something?
To have your display specific properties out of the model, just specify them explicitly in the controller... Otherwise the controller acts as a proxy for its model... just have the property "iamNotPartOfTheModel" in your controller
App.IndexController = Ember.ObjectController.extend({
iamNotPartOfTheModel: null
})
Sample fiddle here
Your controller needs to interface to some kind of model. You can't separate the persisted model from the controller except by some kind of object reference. Even if you don't use ember-data, you'll still need to create objects which then plug into the content of the controller. Have a look at Evil Trout's blog for an implementation of ember without ember-data. Its a great starting point.
All, I am a newbie of Backbone. and I am trying to understand the Model of Backone. Especially how to define a Model. so far, I didn't saw a clear or formal way about how to define a Model for backbone.
For example Let's see the set method in help doc .
set
model.set(attributes, [options])
Set a hash of attributes (one or many) on the model.
Say we have some code like below . I think set method actually is assign a javascript object to the Model.
window.Employee = Backbone.Model.extend({
validate:function(attrs){
for(var key in attrs){
if(attrs[key] == ''){
return key + "can not be null";
}
if(key == 'age' && isNaN(attrs.age)){
return "age is numeric";
}
}
}
});
....
var attr = {}; // I can't not sure what is {} mean.
$('#emp-form input,#emp-form select').each(function(){
var input = $(this);//using jquery select input and select. and enumerate all of them.
attr[input.attr('name')] = input.val();//I am not sure what does it means
});
if(employee.set(attr)){
Employees.create(employee);
}
....
in this example ,I didn't saw the classical way which we can see in java class or c# class to define the class fields or methods. but only see a validate function .Is there anybody who can tell me more about it to help me understand? thanks.
To define a model in Backbone you have to extend the Backbone.Model object. For example if you'll like to create a new User model you could write something like this:
var User = Backbone.Model.extend({})
You can also overwrite some model methods to fill your needs. For example you can change the urlRoot attribute to tell the model where should he fetch the data.
Backbone models contain your data in the attributes attribute. You change those attributes by using the model set method and you can read the value stored in the model using the get method. So if you had some inputs where a user can enter information, for example creating a new user with his name and email and you have a form with a text input for both of them. You could do domething like this:
var user = new User;
user.set('name', $('#name').val());
user.set('email', $('#email').val());
attributes = {
name: user.get('name'),
email: user.get('email')
};
user.save(attributes);
There are a lot of ways to re-factor this code to make it look better but it help to see how you could use those methods. You should check the Backbone documentation to explore how they work a little bit more. Hope this helps!
PD: In my example I set an attribute a time, but you could also send a hash of attributes to set more values in one call.
The model in JS is basically a wrapper for data, with CRUD and simple validation functions. To work properly you need to make server functions to work with (ajax), I think this tutorial says it all http://backbonetutorials.com/what-is-a-model/. Instead of database the model works with your application server side.
If you have custom actions (not just add/edit/remove) on your data, you can manually "set()" data, use "onchange" event and refresh your view when needed. You can even attach "onchange" events only on specific fields and make custom functions in your view to handle each special field (for validation or display).
You can define fields at initialize and defaults value, but not custom functions (ofc you can do model.customFuntion() but I don't recommend it.
In order to make it more "clasical way" you need to use the other Backbone functions http://backbonejs.org/#Collection-Underscore-Methods and Backbone.Collection.
Perhaps this seems a bit backwards, but I have a view bound with Rivets.js for which I'd like the view to populate the model on initialization.
The usecase is that I'm using server-side rendering to return a snippet (the view) including rivets' data-attributes. So NO JSON is returned from server to client.
Now, by pressing 'edit' a user may put the content in 'edit'-mode, and start editing at will. (Using contenteditable, but this is out of scope here I guess).
So how to make sure the model is populated with values from the view on init?
I know that this question is a little outdated but I recentry tried rivets and I came across the same problem.
The solution:
// In your rivets configuration you disable preload:
rivets.configure({
templateDelimiters: ['[[', ']]'],
preloadData: false
});
// you bind your data
var binding = rivets.bind($('#auction'), {auction: auction});
// you manually publish it once to populate your model with form's data
binding.publish();
And that's it. I still don't know how to disable prelaod per bind
From the example on Rivets website (assign to 'rivetBinding')
var view = rivets.bind($('#auction'), {auction: auction});
doing rivetBinding.publish(); will bootstrap the model with values from the view for all bindings that have 'publishes = true'.
This question is old but it still has no accepted answer, so here goes:
You need to disable the preload configuration so rivets doesn't override whatever is in the input with what you have in your model at the time you do the binding. This can be done via the preloadData=false configuration, either globally (rivets.configure(...)) or view-scoped (third param to rivets.bind(...)).
After the binding, you need to publish the view (pull the values to your model). You also need to set up the observers via sync() call, otherwise your binded methods won't be triggered.
Using the same example as the previous answers:
var view = rivets.bind($('#auction'), { auction: auction }, {
preloadData: false
});
view.publish();
view.sync();
My web server returns a page with some structured markup. I need to use knockoutJS to have a markup representation at hand as a JSON object - knockout view model object.
The page basically has (right after initial loading) a <div data-bind="foreach: ExistingNamings"> that has several enclosed divs that actually hold stuff that supposed to go into the ExistingNamings array on the view model object.
Can knockout "parse" and existing markup and populate view model based on the markup provided at the moment of calling ko.applyBindings?
A tutorial on KNJS shows the opposite - we have a data generation code in JS, and that gets pushed into an html upon applyBindings call.
P.S. My server side is ASP.NET MVC, and I've seen people suggesting http://knockoutmvc.com/ - an approach to generate initialization code for js file. This way it is "as if" view model is initialized via javascript. Is this the only way of dealing with initial data, or I indeed can parse markup?
You can directly serialize your C# models into JSON using razor like this:
var serverModel = #Html.Raw(Json.Encode(Model));
or, obviously:
var serverProperty = #Html.Raw(Json.Encode(Model.Property));
The only time this fails is when you have circular references, which can happen if you are dropping your Entity models directly in. If you are doing this, make a ViewModel for them, to eliminate the circular navigation properties.
Update:
To get this into your viewModel, add this to the bottom of your Razor View:
<script type="text/javascript">
var serverModel = #Html.Raw(Json.Encode(Model));
//Define KO viewModel, either here, or by including via script tag in header
ko.applyBinding(new ViewModel(serverModel));
</script>