Knockoutjs observablearray Refresh value - asp.net-mvc

I list my status message with knockoutjs Template Binding. My status mesages have like count. I want when ı click my like button refresh my like count where ı clicked it. How can do it. my knockout model code
var viewModel = {
messages: ko.observableArray()
};
ko.options.useOnlyNativeEvents = true;
ko.applyBindings(viewModel);
$.getJSON('#Url.Action("statusMessages", "Home")', function (data) {
viewModel.messages(data);
});
and my like button clik code
var LikeButtonClick = function (id) {
$.getJSON('#Url.Action("Like", "Home")/' + id).done(function (d) {
if (d.State)
toastr.info("Beğendiniz.");
else
toastr.error("Beğenmekten Vazgeçtiniz");
var message = ko.utils.arrayFirst(viewModel.messages(), function (currentMessage) {
return currentMessage.MessageId == d.Id;
});
if (message) {
console.log(message.MessageId)
// refresh
}
})
};
and my button html code
div class="panel-footer-btn-group pull-right" style="margin-left:5px; display:block;">
<button data-bind="click: LikeButtonClick.bind($root,MessageId)" class="btn btn-default like">
<span data-bind="text:LikeCount"></span> <i class="fa fa-thumbs-o-up"></i>
</button>

It seems like you have an observable property called LikeCount somewhere but you haven't included it in the question.
Somewhere you need to do:
var viewModel = {
messages: ko.observableArray(),
LikeCount: ko.observable();
};
and in your json you need to update that observable:
viewModel.LikeCount(data.LikeCount); //or similar

Related

Knockoutjs Button Click

Hi how can ı get my value with knockoutjs click event my button code
<button data-bind="click : LikeButtonClick , value : MessageId" class="btn btn-default like"><span data-bind="text:LikeCount"></span> <i class="fa fa-thumbs-o-up"></i></button>
and my knockoutjs click code
var LikeButtonClick = function () {
alert("");
}
And how can I refresh my likes after like button click event. I use template binding. My template binding code is
var viewModel = {
messages: ko.observableArray()
};
ko.options.useOnlyNativeEvents = true;
ko.applyBindings(viewModel);
$.getJSON('#Url.Action("statusMessages", "Home")', function (data) {
viewModel.messages(data);
});
and my like button code
var LikeButtonClick = function (id) {
$.ajax({
url: '/Home/Like/' + id,
type: 'POST',
success: function (data) {
// refresh
});
}
});
}
Another method is to build the click function into your data model. Here I've added the function to the item directly. Each click will only affect it's own object information.
function Post() {
var self = this;
self.Text = ko.observable("Lorem Ipsum");
self.Liked = ko.observable(false);
self.LikeCount = ko.computed(function() {
return self.Liked() ? 1 : 0;
});
self.MessageId = ko.observable(1);
self.LikeButtonClick = function() {
self.Liked(!self.Liked());
}
}
function viewModel() {
var self = this;
self.Posts = ko.observableArray();
self.Load = function() {
self.Posts.push(new Post());
self.Posts.push(new Post());
self.Posts.push(new Post());
}
self.Load();
}
ko.applyBindings(new viewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<div data-bind="foreach: Posts">
<div data-bind="text:Text"></div>
<button data-bind="click: LikeButtonClick, value: MessageId" class="btn btn-default like">
<span data-bind="text:LikeCount"></span>
<i class="fa fa-thumbs-o-up"></i></button>
</div>
this context passed to the method will be your viewmodel, or whatever you have bound to the element. Inside LikeButtonClick you should be able to get the value of MessageId by referencing the property this.MessageId().
If you want to pass a value to the click handler, you'll want to declare an inline function where you data-bind, or alternatively, bind the function with a context. Here the context is the main viewmodel:
data-bind="click: LikeButtonClick.bind($root,'green')"
var LikeButtonClick = function (src) {
alert(src); // src='green' in this example
}

Load tabs with Ajax

I have a bootstrap nav-tab and I want to display dynamically content when I select a tab. Each tab must display a div with some text that is returned from ajax call at the controller's action GetSection().
<div class="tabbable">
<ul class="nav nav-tabs" data-bind="foreach: sections">
<li data-bind="css: { active: isSelected }">
<a href="#" data-bind="click: $parent.selectedSection">
<span data-bind="text: name" />
</a>
</li>
</ul>
<div class="tab-content" data-bind="foreach: sections">
<div class="tab-pane" data-bind="css: { active: isSelected }">
<span data-bind="text: 'In section: ' + retValue" />
</div>
</div>
</div>
Javascript code:
var Section = function (name, selected) {
this.name = name;
this.retValue = "";
this.isSelected = ko.computed(function () {
return this === selected();
}, this);
}
var ViewModel = function () {
var self = this;
self.selectedSection = ko.observable();
self.sections = ko.observableArray([
new Section('Tab One', self.selectedSection),
new Section('Tab Two', self.selectedSection),
new Section('Tab Three', self.selectedSection)
]);
self.selectedSection(self.sections()[0]);
self.selectedSection.subscribe(function () {
$.ajax({
url: '#Url.Action("GetSection")',
data: { name: self.selectedSection().name },
type: 'GET',
success: function (data) {
self.selectedSection().retValue=data.text;
}
});
});
}
ko.applyBindings(new ViewModel());
The problem is that retValue from ajax is not displayed. The controller action is this:
public JsonResult GetSection(string name)
{
var ret = new { text = name + "abcd" };
return Json(ret, JsonRequestBehavior.AllowGet);
}
Knockout can only know to update the view for properties that are obsverable (hence the name), so you need to make retValue observable:
var Section = function (name, selected) {
this.name = name; // <-- consider similar change here too
this.retValue = ko.observable(""); // <-- change here
this.isSelected = ko.computed(function () {
return this === selected();
}, this);
}
Then, you need to remember to set an obsverable's value by calling it as a method with the new value as its only argument, e.g.:
$.ajax({
url: '#Url.Action("GetSection")',
data: { name: self.selectedSection().name },
type: 'GET',
success: function (data) {
self.selectedSection().retValue(data.text); // <-- change here
}
});
And finally, if you're binding to a complex expression in your view you need to invoke it as a function (with no arguments) to get its value:
<span data-bind="text: 'In section: ' + retValue()" />
As a side note, realize that you can leave off the parentheses (consider it syntactic sugar from knockout) if you bind straight to just the observable, e.g.:
<span data-bind="text: retValue" />
Which is effectively equivalent to:
<span data-bind="text: retValue()" />
On a foot note, I see you've used this syntax for a click binding:
...
This works... but only by coincidence. You should realize these things together:
$parent.selectedSection contains the result of ko.observable() which means it is in fact a function that can be invoked
the click data-binding will invoke the expression it gets as a function, passing the contextual data (in your case a Section) to that function
So bascially, when the click happens, this happens:
$parent.selectedSection($data) // where $data == the current Section
Which effectively selects the Section.
It would be more verbose though a lot clearer if the $parent had a function:
var self = this;
self.selectChild = function(section) {
// Possibly handle other things here too, e.g. clean-up of the old selected tab
self.selectedSection(section);
}
And then use the click binding in this clear way:
...
On click the selectChild method will be called, again with the contextual data as the argument.
Instead of this
self.selectedSection().retValue=data.text;
Do this
self.selectedSection(data);

JQueryUI dialog as bindable template in KnockoutJS

This question is exposing that one: integrating jquery ui dialog with knockoutjs
I have Model with array of items like this:
var viewModel = {
items: ko.observableArray([])
}
viewModel.items.push(new DialogModel("title 1"));
viewModel.items.push(new DialogModel("title 2"));
viewModel.items.push(new DialogModel("title 3"));
Next I show these items in markup using foreach statement
<div data-bind="foreach: items">
<div data-bind="text: title"></div>
<button data-bind="click: open">Open</button>
<button data-bind="click: close" >Close</button>
</div>
I need to show JQueryUI dialog on clicking buttons and this dialog should be binded to ItemModel instance.
I do not want to include dialog code inside loop because it is copying in result DOM and makes it huge. I'd like to use dialog in template for example.
JSFiddle mockup here http://jsfiddle.net/YmQTW/8/
Any thoughts?
You can create an array that contains only the opened dialogs and bind this array to the template.
With this code only dom of opened dialogs are duplicated.
var DialogModel = function (title) {
var self = this;
self.title = ko.observable(title);
self.isOpen = ko.observable(false);
self.open = function () {
viewModel.shownDialogs.push(self);
setTimeout(function () { self.isOpen(true); }, 0);
};
self.close = function () {
this.isOpen(false);
};
self.isOpen.subscribe(function () {
if(self.isOpen() === false)
viewModel.shownDialogs.remove(self);
})
};
var viewModel = {
items: ko.observableArray([]),
shownDialogs: ko.observableArray([]),
};
The view :
<div data-bind="foreach: shownDialogs">
<div data-bind="template : 'tmpl'"></div>
</div>
See fiddle
I hope it helps.

JQuery UI highlight effect color parameter ignored in Knockout foreach

Im trying to apply the JQuery UI highlight effect to an element when an item that is bound to a knockout observablearray is updated.
The highlight effect is applied but the highlight color used is always the elements current background color. even if I specify the highlight color using the { color: 'XXXXXXX' } option.
any ideas what might be happening?
Thanks,
Steve.
Code below: The element is the span.tag
<div class="row">
<div class="span12">
<div class="tagsinput favs span12" style="height: 100%;" data-bind="foreach: favs, visible: favs().length > 0">
<span class="tag" data-bind="css: $root.selectedFav() == userPrefID() ? 'selected-fav' : '', attr: { id: 'fav_' + userPrefID() }">
<span data-bind="text: name, click: $root.loadFav.bind($data)"></span>
<a class="tagsinput-fav-link"><i class="icon-trash" data-bind="click: $root.delFav.bind($data)"></i></a>
<a class="tagsinput-fav-link-two" data-bind="visible: $root.selectedFav() == userPrefID()"><i class="icon-save" data-bind=" click: $root.saveFav.bind($data)""></i></a>
</span>
</div>
</div>
</div>
// This is the code that does a save via ajax then highlights the element when done.
$.getJSON('#Url.Action("SaveFav","User")', { id: item.userPrefID(), fav: window.JSON.stringify(fav) }, function (result) {
var savedFav = ko.utils.arrayFirst(self.favs(), function (aFav) {
return aFav.userPrefID() == result.userPrefID; // <-- is this the desired fav?
});
// Fav found?
if (savedFav) {
// Update the fav!
savedFav.value(result.value);
}
}).done(function () {
var elementID = "#fav_" + item.userPrefID();
highlightElement(elementID);
});
// Function to highlight the element
function highlightElement(element) {
$(element).effect("highlight", {}, 1500);
}
I would do this the 'knockout' way... use a custom bindingHandler. You shouldn't be directly manipulating DOM in your viewModel, but only touching properties of your viewModel.
Taking this approach, you simply set a boolean value to true when your save is complete... this triggers the highlight effect (the jquery/dom manipulation neatly hidden away from your viewmodel) and when highlight effect completes, the handler sets the boolean back to false. Nice and tidy.
HTML:
<div id="#fav" data-bind="highlight: done">This is a test div</div>
<br />
<button data-bind="click: save">Simulate Save</button>
Javascript:
ko.bindingHandlers.highlight = {
update: function(element, valueAccessor) {
var obs = valueAccessor();
var val = ko.unwrap(obs);
if (val) {
$(element).effect("highlight", {}, 1500, function() {
obs(false);
});
}
}
};
var vm = function() {
var self = this;
self.done = ko.observable(false);
self.save = function() {
self.done(true);
};
}
ko.applyBindings(new vm());
Fiddle:
http://jsfiddle.net/brettwgreen/pd14q4f5/

how to read response when clicked on button of bootstrap popup?

I am developing MVC application. I am using bootstrp for CSS.
I want to use alert/dialog for confirmation on the delete the record.
It should ask for OK/Cancel and according to the button click next process will be carried out...
I have get the below code form some forum, it works fine but didn't get any event if I clicked on OK or cancel button
How to read these click events from below code ?
$('#Deactivate').click(function () {
var href = $(this).attr('href');
if (!$('#dataConfirmModal').length) {
$('body').append('<div id="dataConfirmModal" class="modal" role="dialog" aria-labelledby="dataConfirmLabel" aria-hidden="true"><div class="modal-header"><button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button><h6 id="dataConfirmLabel">Deactivation Confirmation</h6></div><div class="modal-body"><h3>Are you sure to deactive #Model.Name ?</h3> </div><div class="modal-footer"><button class="btn" data-dismiss="modal" aria-hidden="true">Cancel</button><a class="btn btn-primary" id="dataConfirmOK">OK</a></div></div>');
}
$('#dataConfirmModal').find('.modal-body').text($(this).attr('data-confirm'));
$('#dataConfirmOK').attr('href', href);
$('#dataConfirmModal').modal({show:true});
$('#dataConfirmOK').on('click', function(e)
{
alert('#Model.Id');
var url2 = "#Html.Raw(Url.Action("DeactivateParty", "Party", new { #id = "PoNo"}))";
alert(url2);
url2 = url2.replace("PoNo", '#Model.Id');
$.post(url2, function (data) {
if(data == true)
{
var url = $("#RedirectTo").val();
location.href = url ;
}
});
return false;
});
You have to specify an event handler for your Ok button:
$('#dataConfirmOK').on('click', function(e) {
// Call your delete action here
});
It looks like you have a syntax error closing off the post method:
$.post(url2, function (data) {
if(data == true)
{
var url = $("#RedirectTo").val();
location.href = url;
}
Should be...
$.post(url2, function (data) {
if(data == true)
{
var url = $("#RedirectTo").val();
location.href = url ;
}
})
n.b If you dump your posted code into the console window of your favorite browser, you'll see the error.

Resources