Reputation: 1122
I ran into an issue with creating a view model with Knockout.js. The point what I would like to ask is the way to implement a binding of a function that uses an observable as an argument.
I have these classes of Entity Framework:
public class Actor
{
public int Id { get; set; }
public string ActorName { get; set; }
public List<ActorCurrentStatus> ActorStatuses { get; set; }
}
public class ActorCurrentStatus
{
public long Id { get; set; }
public double Rating { get; set; }
public MatchType MatchType { get; set; }
public string CurrentStatusIndicator { get; set; }
//Foreign Key Conditions
public long Actor_Id { get; set; }
public virtual Actor Actor{ get; set; }
}
public enum MatchType
{
type_team,
type_ffa
}
public class ActorsListViewModel //View Model (not in database)
{
public int Id { get; set; }
public List<Actor> Actors { get; set; }
}
Controller passes the list of Actor to the view:
public ActionResult ActorsList()
{
ActorsListViewModel vm= new ActorsListViewModel();
viewModel.vm= _db.Actors.ToList();
return View(vm);
}
Then a js object is created in the view:
<script type="text/javascript">
var model = @Html.Raw(JsonConvert.SerializeObject(Model, Formatting.Indented,
new JsonSerializerSettings()
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
}));
</script>
And it gets to be a viewModel by ko.mapping.fromJS with the following mapping option:
var mapping = {
create: function (raw) {
var modelBase = ko.mapping.fromJS(raw.data);
//using linq.js
modelBase.getActorStatus = function (data, modeStr) {
return Enumerable.From(ko.mapping.toJS(data)).Single(t => t.CurrentStatusIndicator == modeStr);
}
modelBase.mode = ko.observable('type_team');
return modelBase;
}
}
var viewModel = ko.mapping.fromJS(model, mapping);
ko.applyBindings(viewModel);
Here this works correctly:
<div data-bind="foreach: Actors()">
<div data-bind="text: $parent.getActorStatus(ActorStatuses ,'type_team').Rating"></div>
</div>
But I have a problem when I try to use the observable of modelBase.mode to set a condition for the binding, so I have inserted these contents to the view:
<button data-bind="click: ChangeMode('type_team')">TYPE_TEAM</button>
<button data-bind="click: ChangeMode('type_ffa')">TYPE_FFA</button>
and change the binding to:
<div data-bind="text: $parent.getActorStatus(ActorStatuses ,$parent.mode).Rating"></div>
Where the function ChangeMode is like this:
function ChangeMode(str) {
switch (str) {
case 'type_team':
viewModel.mode = 'type_team';
break;
case 'type_ffa':
viewModel.mode = 'type_ffa';
break;
default:
break;
}
}
After changing the binding, the view starts to display actors' rating of type_ffa when it is loaded and won't to update the information when I click the buttons.
Could anyone suggests what faults are there in the code and the structure?
Upvotes: 0
Views: 1051
Reputation: 2350
Observable object requires you to assign the value by passing it as an argument. So it needs you to do the following:
function ChangeMode(str) {
switch (str) {
case 'type_team':
viewModel.mode('type_team');
break;
case 'type_ffa':
viewModel.mode('type_ffa');
break;
default:
break;
}
}
Also from the way ChangeMode
function is structured, I believe the function is not bind together when ko.applyBindings
is called. Which means this is just a normal javascript function. Therefore you can't use data-bind: click
to trigger this and instead use a normal onclick.
<button onClick="ChangeMode('type_team')">TYPE_TEAM</button>
<button onClick="ChangeMode('type_ffa')">TYPE_FFA</button>
Upvotes: 1
Reputation: 121
Check this link http://knockoutjs.com/documentation/click-binding.html
You need to bind the ChangeMode function in mapping.
Upvotes: 1