knockout doesn't update html after get data from ajax - mvvm

I bind list of data to HTML, in each list has button for get details by ajax. I want to bind callback data to member of model, After ajax call back, object have data, view received ( ko.toJSON(d, null, 2))object. But HTML doesn't update data.
I don't know what is wrong. please help. Thank you.
Html:
<section id="lists">
<article class="todoList">
<script type="text/html" id="person-template">
<!-- <p>Credits: <span data-bind="text: message"></span></p>-->
<p>xxx</p>
</script>
<ul data-bind="foreach: Items">
<li>
<div>
<span class="contentarea" data-bind="text: message"></span>
<button data-bind="click: $parent.evClick.bind($data)">Get details</button>
<button data-bind="click: detail">Ajax-Get</button>
<p>Credits: <span data-bind="text: d.message"></span></p>
<div style="display: block; width: 200px; height: 200px; border: solid 1px #ff6a00;" data-bind="text: ko.toJSON(d, null, 2)"></div>
</div>
</li>
</ul>
</article>
</section>
Full code here.
http://jsfiddle.net/wuttipat/sc8fX/12/

You should use
<div data-bind="with: d">
<span data-bind="text: message"></span>
Because data-bind="with: d" create scope for binding context when you use data-bind="text: message" inside it will reference to parent binding context in this case mean d.
Full code here : http://jsfiddle.net/sc8fX/74/

I think I've figured it out (after cleaning up the fiddle some more). You're binding is
text: d.message
But it should be
text: message
Because d is the context of your binding. So you're actually trying to bind to d.d.message which doesn't exist. Replacing it with text: message seemed to work, no?
See this updated fiddle.

I found the issue posted on knockout document.
http://knockoutjs.com/documentation/with-binding.html

Related

Knockout 3.2 applyBindings to new dom node

I have searched, and found old answers to this, and hacks about manually clearing bidnigns, and then calling applybindings... as well as creating a custom viewmodel that isnt directly related to anythign else and applying bindings with that AFTER the new dom nodes appear.
My specific scenario is that a bootstrap3 modal basically re-attaches itself after show is called, and likewise none of the items in the modal actually still bound.
I already have a model that represents state/properties of the dialog, but I'd like the dialogviewmodel to be a child of my pageViewModel.
My question is, at this point in time, whats the most appropriate way to do this? Is there no way to say take this node, attach it to the viewmodel at this property?
I am using the same tools as you (knockout and bootstrap3). This is how I accomplish Modals as an example:
This div exists as the first element of the body in my index.html:
<div class="modal fade" id="BaseModal" tabindex="-1" role="dialog" aria-labelledby="BaseModal" aria-hidden="true" data-backdrop="static" data-keyboard="false">
<div id="modalLoading" class="ajax-loader">
<img src="images/working_blue.gif" />
</div>
<div class="modal-dialog modal-lg">
<div id="ModalAnchor" class="modal-content col-lg-4 col-lg-offset-4" data-bind="html: $data.ModalContent"></div>
</div>
</div>
// This is typescript but the javascript should be pretty close to this.
private LoadModalView(viewName: string, viewModel: any): void {
$.get(viewName)
.then((view: any, status: string, jxhr: JQueryXHR) => {
this.ModalContent(''); // ensure there is no content in the modal.
this.ModalContent(view); // Load new HTML
ko.applyBindingsToDescendants(viewModel, this.ModalAnchor[0]); // bind new modal viewmodel
this.BaseModal.modal('show'); // Open the modal
}, (view: any, status: string, jxhr: JQueryXHR) => { /*Do error handling*/ });
}
EDIT: Here is an example of the HTML I load into the modal:
<div class="modal-header">
<h3 data-bind="text: $data.Header"></h3>
</div>
<div class="modal-body">
<h5 data-bind="text: $data.Message"></h5>
</div>
<div class="modal-footer">
<button id="OK" class="btn btn-primary center-block" data-bind="click: OK, text: ButtonText" />
</div>
In the LoadModalView function, the ViewModel parameter is a viewmodel to represent the new data/content/etc of the new modal.
In the Modal Viewmodel, I call 'hide' on the modal when it's purpose is served.
I hope this helps! I don't know if it's the 'correct' or 'proper' way to do this, but this is my pattern.

In JSSOR, how to access the current caption via Javascript?

I would like to pass a value from a slide out of JSSOR to other parts of the DOM.
Markup:
<div class="slide">
<img data-u="image" src="bilder/bild2.jpg" />
<div class="caption" data-u="caption" ><p>Caption text</p></div>
</div>
JS:
jssor_slider1.$On($JssorSlider$.$EVT_PARK,function(slideIndex,fromIndex){
$(".outer-caption").text(currentCaption);
});
The custom JSSOR Event, EVT_PARK, works fine. But what's missing is how to get the caption of the current slide and put it into the variable currentCaption. How to do that?
And if so, where could I have found that out on my own?
Please have a full test of following code,
<div class="slide">
<img data-u="image" src="bilder/bild2.jpg" />
<div class="caption" data-u="caption" id="caption-slide-0"><p>Slide 0 Caption</p></div>
</div>
jssor_slider1.$On($JssorSlider$.$EVT_PARK,function(slideIndex,fromIndex){
$("#outer-caption").text($("#caption-slide-" + slideIndex).text());
});

afterAdd binding is not working

I tried to use the afterAdd binding to add some trivial animation to the elements being added to my observableArray but it does not trigger anything.
I tought I had a problem with my animation code so I coded a small alert on the function but still does not work.
Here's some sample code for the div being templated:
<div id="resultList"
data-bind='template: { name: "searchResultTemplate",
afterAdd: function(elem){alert(elem)} }'
runat="server">
</div>
This is the template:
<script type="text/html" id="searchResultTemplate">{{each(i, searchresult) resultCollection()}}
<div class="searchresultwrapper ui-corner-all ui-state-default">
<div class="searchresult">
<img src='${ ImageUrl }' alt='${ Title }' title='${ Title }' class="searchresultpicture" />
<div class="searchresultinformationcontainer">
<span class="searchresulttitle" data-bind="text: Title"></span>
<br />
<div class="searchresultdescription" data-bind="text: Description">
</div>
<span class="searchresultAuthor" data-bind="text: AuthorName"></span> at <span class="searchresultmodule" data-bind="text: ModuleName"></span> on <span class="searchresultdate" data-bind="text: PublicationDate"></span>
<br />
Take me there
</div>
</div>
</div>
<br />{{/each}}
</script>
Any ideas?
You need to qualify the template attributes with foreach like so,
<div id="resultList" data-bind='template: {
name: "searchResultTemplate",
foreach: searchresult,
beforeRemove: function(elem) { $(elem).slideUp() },
afterAdd: function(elem) { $(elem).hide().slideDown() }
}' runat="server">
</div>
and then, not use {{each in the template, just template it for each item stand alone.
Here, foreach attribute helps keep track of changes to the object array

hpple html parse block by block or property by property?

I'm new about hpple and xpath. for the below html code,I want to get both "title" and "tag" information.
From hpple's example code, I can get a array of title, and another array of tag. But if there are six properties I'm interested, there will be six arrays.
can I find the div[class="entry"], then get its child's , div[class="meta"]? (can anybody share the code?)
Thanks.
<div class="content">
<div id="1" class="entry">
<h2 class="title"> title for entry 1 </h2>
<div class="meta"> tag:xxx </div>
</div>
<div id="2" class="entry">
<h2 class="title"> title for entry 2 </h2>
<div class="meta"> tag:xxx </div>
</div>
...
</div>
#"//div[#class='content']//div[#class='entry']//div[#class='meta']"
This returns tag:xxx for both entries.
I want to get both "title" and "tag" information
//div[#class='content']/div[#class='entry']/*[#class='meta' or #class=title"']
This XPath gets all tags with class title or meta children of div class entry child of any div class content.

How to get the index of the ACTIVE CHILD div of my container with jQuery?

<div id="container">
<div class="active">
<div class="active"></div>
</div>
<div>
</div>
</div>
How to write such a container?
Use .index() without parameters to get it's (0-based) index amongst siblings, like this:
var index = $("#container .active").index();
You can test it out here. For your example markup, it would be 0.