AJAXControlToolkit TabContainer - bug in dynamically adding/removing tabs? - ajaxcontroltoolkit

I am using AjaxControlToolkit version 4.1.40412.0, .NET 4.0, VS2010
Using the TabContainer control I want to add/remove tabs dynamically, but it looks like all of my dynamic changes are not persistent. Here is my scenario: I start with a tabcontainer with 1 tabpanel (hardcoded, i.e. added at design time), then dynamically I add more tabpanels and hide the original tabpanel (run time). As expected I see only the new tabpanels on the page, however any time I try to select a different tab the whole control reverts back to its design time state, i.e. only shows the original tabpanel, which was supposed to be gone and the new tabpanels are nowhere to be found. What am I missing? I guess as a workaround I can add 50 or so tabs at design time and then dynamically hide/display rather than remove/add, but this seems clunky, sloppy and unnecessary.
Here is my code if you want to duplicate the issue:
ASPX
<%# Page Language="vb" AutoEventWireup="false" CodeBehind="WebForm1.aspx.vb" Inherits="WebApplication1.WebForm1" %>
<%# Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="asp" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ToolkitScriptManager ID="ToolkitScriptManager1" runat="server"/>
<asp:TabContainer ID="tcMain" runat="server" AutoPostBack="true" ScrollBars="auto" >
<asp:TabPanel ID="tbTab0" runat="server" HeaderText="Tab0"/>
</asp:TabContainer>
</div>
</form>
</body>
</html>
ASPX.VB
Public Class WebForm1
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not Page.IsPostBack Then
For i As Integer = 0 To 3
Dim ol As New Label
ol.Text = i.ToString
Dim oT As New AjaxControlToolkit.TabPanel
oT.Controls.Add(ol)
oT.HeaderText = i.ToString
tcMain.Tabs.Add(oT)
Next
For i As Integer = 1 To tcMain.Tabs.Count
If tcMain.Tabs(tcMain.Tabs.Count - i).HeaderText = "Tab0" Then tcMain.Tabs.RemoveAt(tcMain.Tabs.Count - i)
Next
End If
End Sub
End Class
Note: If you comment out "If Not Page.IsPostBack Then" , i.e. run the code under it on every page load, the tabcontainer works as expected - I can select any tab without problems. In my real project this cannot be the solution though - I will be adding/removing tabs based on user input, so unless I keep a log of all changes ever made to the control I cannot load those changes every time the page loads.

You need to run your code in the page init or pre init, because by the page load, the page is already built along with the view state.

Related

ZK Textbox content containing <html> tag

When I put the string '' into a ZK Textbox, that is
<textbox value="<html>" />
it causes a JavaScript error in the browser
Uncaught SyntaxError: Unexpected token ILLEGAL
and I can see in the developer tools of the browser that the generated JS code is really incomplete:
zkmx(
[0,'g2JQ_',{dt:'z_y20',cu:'\x2Fdtag',uu:'\x2Fdtag\x2Fzkau',ru:'\x2Fzul\x2Fcomponent\x2Fmenu.zul',style:'width\x3A100\x25\x3B',ct:true},[
...
['zul.inp.Textbox','g2JQp7',{id:'tb',$$0onBlur:true,$$0onSwipe:true,$$0onError:true,$$0onAfterSize:true,$$0onChanging:true,$$1onChange:true,$$1onSelection:true,$$0onFocus:true,width:'500px',style:'font-size:11px;',_value:'
</div>
How can I escape the content of the textbox so that I can display any HTML code in the textbox?
I tried
Replace '<' with '> but then > is displayed.
I also tried
<![CDATA[ <html></html>]]>
but then it was literally displayed, that is, also the
<![CDATA[
UPDATE
It is somehow due to the fact that we have JSPs containing several ZK pages.
And the exact content what causes problem is the closing HTML tag
</html>
The workaround is the following:
Events.echoEvent("onLater", txtDescription, txtDescription);
txtDescription.addEventListener("onLater", new EventListener<Event>() {
#Override
public void onEvent(Event event) throws Exception {
txtDescription.setValue("<html>...</html>");
}
});
Normally you should get values from your composer or viewmodel, and then this problem doesn't exist.
If you want to do it in the zul, you can make a parameter in zscript like this :
<zscript>
<![CDATA[
String a = "<html>";
]]>
</zscript>
<textbox value="${a}" />
Here I created a fiddle so you can test it.
Many time we have saved HTML code in database but when we are going to display that saved value in zk page it show HTML code as well with data .
To resolve this issue we have to use HTML escape there are plenty of way to fix this
You can do it on Java side as well zul page and here is simple way how you can achieve in the zul page
<html>
<![CDATA[
${vm.accessYourValue}
]]>
</html>

How to navigate DOM from Wicket

I wonder if it is possible to modify the HTML code of the parent of a wicket component in the Java code to modify its attribute without making it a component in wicket. For example, I would like to add active to the li tag from Java.
<li>
<a wicket:id="home" href="#">
<i class="icon-home"></i>
<span>Home</span>
</a>
</li>
and the say add an Attribute to that parent without referencing it in code as a component.
I don't think this is possible, it would be completely against the modular nature of Wicket. (Not to mention the fact that pages are actually rendered as a stream, there's no DOM tree built.)
Components in Wicket shouldn't depend on what's outside of them. What if you want to change the logic of active/inactive controls? Or, in a more likely scenario, you just want to change the markup. Or if you just want to unit test your component without any surrounding markup.
Wicket was designed to avoid these "spooky actions at a distance", to create components that are genuinely testable on their own.
You need a component that encapsulates the entire list, which keeps track of which of its items is active (via its model). It might seem at first like a lot of work but when you look at the result, you'll realise how much easier it is to understand what's going on.
You can do it using javascript. In this example I overrided the renderHead() of the link, but it can also be done with a Behavior.
public class TestPage extends WebPage {
public TestPage(final PageParameters parameters) {
super(parameters);
add(new AjaxLink<Void>("link") {
boolean active = false;
#Override
public void onClick(AjaxRequestTarget target) {
active = !active;
target.add(this);
}
#Override
public void renderHead(IHeaderResponse response) {
super.renderHead(response);
String addOrRemove = (active) ? ".addClass('active')" : ".removeClass('active')";
response.render(OnDomReadyHeaderItem.forScript("$('#" + getMarkupId() + "').parent('li')" + addOrRemove + ";"));
}
});
}
}
<!DOCTYPE html>
<html xmlns:wicket="http://wicket.apache.org">
<head>
<style type="text/css">
li.active {background-color: red;}
</style>
</head>
<body>
<ul>
<li><a wicket:id="link">TOGGLE</a></li>
</ul>
</body>
</html>
Yes, it will couple the code to the markup, but this is not always a problem. If you feel you are copying and pasting this code over and over, consider creating a proper component :)

Why Isn't The Partial File Automatically Created?

Getting through Michael Hartl's tutorial great; I've encountered a few snags along the way but nonetheless, it's working out better than I expected.
My question, is regarding the partial file. In the tutorial if I have read correctly, chapter 5- it advises to edit the 'application.html.erb' file with...
'<!DOCTYPE html>
<html>
<head>
<title><%= full_title(yield(:title)) %></title>
<%= stylesheet_link_tag "application", media: "all",
"data-turbolinks-track" => true %>
<%= javascript_include_tag "application", "data-turbolinks-track" => true %>
<%= csrf_meta_tags %>
<%= render 'layouts/shim' %>
</head>
<body>
<%= render 'layouts/header' %>
<div class="container">
<%= yield %>
</div>
</body>
</html>'
The tutorial then says if this line worked I should find a file called 'app/views/layouts/_shim.html.erb' and I cannot find it, thus, it was not automatically created, further not allowing me to pull up the referring static page in my browser (which may or may not be related).
Thanks in advance.
Of course, to get the partial to work, we have to fill it with some content; in the case of the shim partial, this is just the three lines of shim code from Listing 5.1; the result appears in Listing 5.10.
So yes. You have to create partial file by yourself and fill it with proper content. In case you code editor doesn't support partial extraction.
For example:
Using rails.vim plugin for VIM there is the possibility to extract selected lines into partial by using Rextract <partial_name> command. Which creates new file, moves selected lines into it and replace selected lines from source file with <%= render :partial => '<partial_name>' %>

Is the inputmode attribute valid (in HTML5 forms) or not?

I am getting validation errors with the inputmode attribute on text areas and text fields. The validator tells me Attribute inputmode not allowed on element input at this point but the HTML5 spec indicates that it is allowed.
Is there actually something wrong with this code, or is the validator at fault?
Here is a bare bones case which will produce exactly this kind of validation error (twice), in one case on an email input, and on the other on a textarea.
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
</head>
<body>
<form method="post" action="contactme.php">
<label class='pas block'>
Your E-Mail:<br/>
<input type='email' name='email' required inputmode='latin' placeholder='your e-mail here' />
</label>
<label class='pas block'>
Your Message:<br/>
<textarea name='message' required inputmode='latin' placeholder='and your message here!'></textarea>
</label>
</form>
</body>
</html>
Also, see the chart about which attributes apply to the different input types here:
http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#attr-input-type
The "inputmode" attribute applies only to "text" and "search".
UPDATE 2019-09-04: "inputmode" is now a global attribute (per WHATWG) and can be specified on any HTML element: https://html.spec.whatwg.org/multipage/dom.html#global-attributes
Another reference page for "inputmode":
https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/inputmode
On another note, "inputmode" is not a W3C HTML5 attribute, but it is a W3C HTML 5.1 attribute (at least at the time I'm writing this). UPDATE 2019-09-04: "inputmode" has been removed from HTML 5.2 and HTML 5.3.
The HTML5 spec says
The following content attributes must not be specified and do not apply to the element: accept, alt, checked, dirname, formaction, formenctype, formmethod, formnovalidate, formtarget, height, inputmode, max, min, src, step, and width.
It's under bookkeeping details at https://html.spec.whatwg.org/multipage/input.html#e-mail-state-(type=email)
Five years after the question was asked, some may wonder why some of the properties listed by #dsas doesn't trigger such errors, like enctype
The answer is simple support, while enctype for instance gained a wide support
inputmethod is supported only as of IE11 and Edge 14, for more infos click here

Testing Wicket panels with constructor arguments

I got a page with several panels that takes several parameters in their constructors.
One of them being a menu that takes a list for the different buttons in the menu.
I've tried to test it as components but get a null pointer exception. Using a dummy page and creating the panel on the dummy page works.
I'm not entirely happy with this approach since it introduces a lot of new code in my tests and more possibilities for errors.
Is there a better way of testing panels that takes arguments in their constructor?
Sure thing:
The code that gives an null pointer error:
public void testVisitPanel(){
VisitPanel v = new VisitPanel("visitPanel");
tester.startComponent(v);
tester.assertContains("DATE");
}
The panel
public VisitPanel(String id) {
super(id);
add( new Label("visitDate", "DATE"));
add( new Label("visitStage", "VISIT SIGNED"));
}
And the html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:wicket="http://wicket.sourceforge.net/"
xml:lang="en"
lang="en">
<wicket:head>
</wicket:head>
<body>
<wicket:panel>
<span wicket:id="visitDate">VISIT DATE</span>
<span wicket:id="visitStage">STAGE</span>
</wicket:panel>
</body>
</html>
If you're using Wicket 1.4, you probably want wicketTester.startPanel.
What I do is create an implementation of ITestPanelSource in the test, doing something like:
private class TestPanelSource implements ITestPanelSource {
private static final long serialVersionUID = 1L;
public Panel getTestPanel(String panelId) {
return new MyPanel(panelId, myArg1, myArg2);
}
}
with the myArgN being fields in the test class (frequently mocks) that suit the constructor, and then call it in the test or in a setUp method with
wicketTester.startPanel(new TestPanelSource());
This is basically doing some of the DummyPage work for you, so it may not be that far from what you're doing now, but might at least save on implementation of dummy pages for test infrastructure.
In Wicket 1.5, this is deprecated in favor the component testing that you referenced in the question. That should also work, so it might be worthwhile to post some actual code that is giving you trouble with that technique.