How to Animate the if body in knockoutjs? - javascript

I have one knockoutjs observable variable called "state" and i am using that variable to hide and show content in knockout with if condition like below:
<--if: state()=="login" -->
login content
<--/if-->
<--if: state()=="registration" -->
registration content
<--/if-->
whenever state variable changes it shows or hides the content. So my question is that i want to add animation of toggling behavior when it hides or shows for this. how would i be able to do it?

I did a quick fiddle for you.
http://jsfiddle.net/ujSvb/1/
for a more dynamic example
http://jsfiddle.net/ujSvb/2/

I further updated Anders' fiddle to add the state condition:
http://jsfiddle.net/ujSvb/3/

First, I think you may have some error in your code there(may have just copied it over wrong) but it should be:
<-- ko if: state()=="login" -->
login content
<--/ko-->
<-- ko if: state()=="registration" -->
registration content
<--/ko-->
Second, if you can use jQuery along with binding on elements instead of using virtual elements such as:
<div data-bind="if: state()=="login">
You can utilize Knockout's bindingHandlers. I have created an ifTransition binding which does what you want. Here's a fiddle with the bindingHandler and a sample of it in action:
http://jsfiddle.net/Rynan/vtPT8/
Update
Okay, I updated my fiddle to utilize the virtual elements but you will still have to wrap your login and registration content within a div to get the transition affect you are looking for. Keeping with your comment, that div won't be rendered until the state has changed to whatever it needs to be to display those certain contents so it won't take much memory while it isn't in the correct state.

Top voted answer isn't a solution since it doesn't unrender the elements.
Austins answer doesn't appear to work at all.
See my response in:
Animation before 'with' binding update
for a clean workaround I've discovered, replacing 'if' and 'with' with roughly equivalent 'template' bindings.

Related

AngularJS event which is triggered after all scopes are applied

I have a AngularJS application where I am loading data from a REST service.
Now what sometimes happens is that the brackets {{}} used to access values from scope are rendered and after that replaced by the real values. Now what I d like to do is add a ng-switch to the top DIV of the application and check whether a global var (e.g. pageLoaded (true|false)) is true or false. If its true, I d like to load the normal page, if its false, I d like to print something like "loading...". So my problem is how can I get notified (e.g. through a Angular Event) if all the data is ready, and is added to scope? Because after that I dlike to set pageLoaded to true.
Is there a way to do this in a generic way? I don't like to implement this per page.
Thanks a lot in advance.
Greets
Marc
You should use ng-cloak for that - http://docs.angularjs.org/api/ng.directive:ngCloak
For showing a loading panel, you can do something like:
<div ng-hide="true">Loading...</div>
So when angular finishes loading, ng-hide will occur and hide the loading panel.
Use ng-cloak to get rid of this sort of problems. And make sure you apply the ng-cloak directive to the body of the page so that this doesn't show up till the data is loaded properly. And use the following styling in your CSS file.
[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
display: none;
}
Note: you can even create some other element or div, thats something like a popup or notification bar, which shows "please wait till the data is comnpletely loaded". Set this div to display:none initially and in the Ajax call, change the display property to block/inline as needed and finally make it dispay:none after the success call back.. :)
One of the solutions is you can use ng-bind instead of using {{}} which will show ugly {{}} when the value is not rendered.
<div ng-bind="value">Loading ...</div>
For anyone who is having a problem more to do with the actual question than OP's specific scenario:
I had a fragment that was getting loaded-in after/by the main partial that came in via routing.
I needed to run a function after that subpartial loaded and I didn't want to write a new directive and figured out you could use a cheeky ngIf
Controller of parent partial:
$scope.subIsLoaded = function() { /*do stuff*/; return true; };
HTML of subpartial
<element ng-if="subIsLoaded()"><!-- more html --></element>

Content with queryui checkbox button grows when is replaced with Backbone.js

I have the next code to replace content using Backbone.js
jsfiddle
I don't know why the checkbox button grows when the content is replaced.
Simply, I use the next code to checkbox
$('.checkWeek').button();
I think the reason is because you keep calling the $('.checkWeek').button(); on every click so JQuery does something funny and adds a span within a span which causes the size to grow.
A simple fix is to not call the $('.checkWeek').button(); if the button already exists (or shown)
// if button already exists then dont add it again.
if(!$('label[for=checkWeekM]').hasClass('ui-button'))
$('.checkWeek').button();
Look here: http://jsfiddle.net/Thxtr/3/
At the moment code stores the templates in div tags - every time you call button the template is modified. You can avoid that by using a script tag with type text/template so that it won't be executed as Javascript.
Rigth now:
<div data-template-name="central-home">
<div data-template-name="">
<input type="checkbox" class="checkWeek" id="checkWeekM" />
<label for="checkWeekM">L</label>
</div>
</div>
Change to:
<script data-template-name="central-home">
<div data-template-name="">
<input type="checkbox" class="checkWeek" id="checkWeekM" /><label for="checkWeekM">L</label>
</div>
</script>
With the Javascript unchanged the template will not be found. So you also have to update this line:
content.view = ...$.trim($("[data-template-name='"+ template_name +"'] div").html()...
With the requirement for the template to be inside a div removed:
content.view = ...$.trim($("[data-template-name='"+ template_name +"']").html() ...
Working fiddle
I'm guessing that $('.checkWeek').button() only needs to be called once per .checkweek element, or maybe just once in total.
If so then possible workarounds would be :
to execute $('.checkWeek').button() conditionally (though I'm not sure what the test might be).
to make the $('.checkWeek') selector more selective, ie select only the freshly added element.
if a destroy option exists, to call $('.checkWeek').button('destroy').button() (or similar - you will have to search through the plugin's API documentation).
Without a more complete understanding of the app (and the plugins), I can't tell which of these possibilities is most appropriate.

How to use inline ternary with data-bind variable?

I'm currently creating a footer with Save/Cancel/Delete, depending on where the user is. Now I'm trying to not show/render the Delete button when it's not required. How to achieve this using a variable from KnockoutJS (observable) as the operator in a ternary?
Current code doesn't work properly but below anyway.
<li>#(Global.ButtonCancel)</li>
<script>
var button = "<li>#(Global.ButtonDelete)</li>";
isEditingProduct ? button : false;
</script>
<li>#(Global.ButtonSave)</li>
The error i keep getting is that "isEditingProduct" is undefined. When i use it inline (outside the script), for a straight <li data-bind="isEditingProduct" ></li> with the other stuff inside it works. It hides the button, but leaves me with a gaping hole in the footer. Which is why I'm trying to get around it by not loading it in for rendering at all if it's not yet needed.
Any help would be appreciated.
Taking a look at your code, I'm confused.
No idea why you feel you need a ternary to hide/unhide elements.
Use the visible: binding.
<li data-bind="visible: isEditingProduct"></li>
isEditingProduct needs to be a property on your view model.
You could use visible or if binding:
<li>#(Global.ButtonCancel)</li>
<li>#(Global.ButtonDelete)</li>
<li>#(Global.ButtonSave)</li>
Read documentation about these bindings:
http://knockoutjs.com/documentation/if-binding.html
http://knockoutjs.com/documentation/visible-binding.html
Not sure where you "isEditingProduct" is defined but you can't simply reference a part of your View Model in JavaScript without fully qualifying it. Instead try:
myViewModel.isEditingProducts = true;
Also, the location of your script block is confusing. It shouldn't be in-lined between <li /> tags. The script will not necessarily execute at that time (as the browser is parsing your markup).

How to use onmouseover?

I have a list being displayed on a JSP. On mouse hover on any of the value i need to show a description corresponding that value. Need to show description not as an alert and also cannot make the values as hyperlink.
eg.
suppose the value is ABC so on mouse hover should show AppleBoyCat.
need to use onmouseover. let me know how to do it..
What do you want to do? If you just want to show a tooltip, you can set the title attribute of any element and it will be displayed as a tooltip.
Also, the abbr tag can be used as tooltips too:
<abbr title="test">stuff</abbr>
You can go about it in two ways:
1 - a hidden dom object (a div for instance) which reveals itself when you roll over whatever
or
2 - you can rewrite the html of the particular element you're mousing over.
You can load this data in when you load everything else (either as Javascript objects, or as markup, though that's much bulkier) or you can asynchronously load the description data from a service when you mouse over (though you'll have more lag).
jQuery is a quick and dirty way to achieve this (more quick than dirty), but straight JS or pretty much any other JS library will do as well.
Perhaps not the cleanest solution but something like this:
<a class='hover' rel='tooltip'>Link</a>
//Some hidden div, putting css inline just for example
<div id='tooltip' style='display:none;'>Content</div>
$(function() {
$('.hover').mouseover(function() {
var tooltip = $(this).attr('rel');
$('#' + tooltip).fadeIn();
});
});
And offcourse add a callback hiding it again. It just takes the value from rel of the link and use as an id for the div to show.
This is a quick and dirty solution, can be made alot smoother if you just work with it a little;)
There also alot of plugins out there allowing the same functionality in a cleaner fashion.
*Edit: Just noticed you added a comment on another post that you can't use jQuery.. shouldn't tag a post with something you're not intending to use.
As TJHeuvel already said, you can simply use the title attribute.
Best approach is to build the list with both the value and title attribute from within JSP, if not possible for some reason, you can build client side array of each value and its corresponding description then using JavaScript dynamically assign the title on mouseover.
Show us some more code to get more/better help.
For simple tooltips, the title attribute is most effective, as pointed out by TJHeuvel
If you need more advanced tooltips with HTML and CSS formatting, I'd suggest you use an external library.
One that works nicely without jQuery ist wz_tooltip download here, documentation here
When included correctly, you can add tooltips by calling the functions Tip() and UnTip() as follows:
Homepage

Removing appended html using jQuery?

Using jquery, I currently append html to a div on a click event. The following code allows me to fade in only the appended portion of the div:
var html = "..";
$('<div></div>').appendTo("#id").hide().append(html).fadeIn('slow');
This portion works perfectly. But how can I later remove (fade out) only the appended portion? I tried hacking this by storing the html prior to the appending, and then simply hiding everything and showing the stored html. But this does not work well when the same procedure is reused for several divs on the same page (and this seems like poor implementation). Is there a good way to do this?
Just to give an idea of why I need this: Think of a blog type page where for every article on the page there are several comments with only x amount showing by default: the click event fetches the remaining comments and displays them, and then toggling the button again removes the appended comments and sends it back to the original state.
empty() is always an option
jQuery('#main').empty();
Give a look at the empty() function.
It might better solve the problem. Here's the link http://api.jquery.com/empty/
I'd just set and clear the html with '.html()' ...
-- edit
to be more clear, have an area layed out specifically for the addition of these comments:
<div id='commentarea1'></div>
etc.
Try:
var html = "..";
$('<div></div>').appendTo("#id").hide().append(html).fadeIn('slow').addClass('appended');
then later
$('#id .appended').fadeOut('slow'); // or whatever you want to do.
It is not that clear from the question but say you show 5 comments by default and then show x more comments. To get back to the original 5 comment default state you can remove all comments with an index greater than 4 (zero based).
The following assumes each comment goes inside its own div that has a class comment.
$('#id>div.comment:gt(4)').remove();

Categories

Resources