What's the proper way to go about it. I need it to work like in the example below.
<input type="button" value="Resume" onclick="window.location = '/Test?testid=#(ViewBag.TestID)'" />
I absolutely support Zabavsky's comment that you should use an ActionLink for this specific example in order to have semantically correct markup.
But since you asked:
Mixing razor syntax with Javascript in views
Never do that.
In your view you should have only markup:
<input type="button" value="Resume" id="myButton" data-url="#Url.Action("Test", new { testid = ViewBag.TestID })" />
and javascript (IN A SEPARATE FILE) where you could work with this markup and unobtrusively enhance it:
$(function() {
$('#myButton').click(function() {
window.location.href = $(this).data('url');
});
});
Of course if the user has javascript disabled your web application is completely busted. That's why you should always write semantically correct markup. In this case that would be to use an anchor because in HTML buttons are used to submit forms, anchors are used to redirect to some other location (which is exactly what you are trying to achieve in this specific case).
I would, as Zabavsky said, use an ActionLink for this:
Something like this:
#Html.ActionLink("Resume", "Test", new { testid = ViewBag.TestID })
There are quite a few overrides for actionlink, so you need to pick the one which fits your needs.
The one above output an a href with the text 'Resume' going to action 'Test' on the current controller, passing a routevalue of testid = ViewBag.TestID
You can do it like:
<html><head><script>function newDoc() { window.location.assign("http://www.abc.com") }</script></head><body><input type="button" value="Load new document" onclick="newDoc()"></body></html>
Hope it will help. Thanks.
Well, what you wrote is valid.
You may have VS underline your code in red cause it think you have a js error due to the '' string not ended... but if you run it, it works.
To avoid red underline, you could do :
#{string js = "window.location = '/Test?testid="+ViewBag.TestID+" '";}
<input type="button" value="Resume" onclick="#js" />
Related
I'm trying make some stuff in jQuery using ASP.NET. But the ID from runat="server" is not the same as the id used in HTML.
I used to use this to get the ID from this situation:
$("#<%=txtTest.ClientID%>").val();
But in this case, it does not work. I'm clueless as to why.
Javascript
/* Modal */
function contatoModal() {
//alert("Test");
alert($("#<%=txtTest.ClientID%>").val());
}
HTML
< input runat="server" id="txtTest" value="test" />
Any tips?
<%= txtTest.ClientID %> should work but not in a separate javascript file where server side scripts do not execute. Another possibility is to use a class selector:
<input runat="server" id="txtTest" value="test" class="txtTest" />
and then:
var value = $('.txtTest').val();
In WebForm / HTML Page....
<asp:TextBox ID="txtUserName" runat="server" Class="form-control"></asp:TextBox>
In Jquery
var UserName = $("[id*=txtUserName]").val();
alert(UserName);
100% Sure its Working for me....
As others have mentioned, you can pass a class selector to jQuery, but that is a bit messy. I prefer to use the jQuery attribute ends with selector. Given that a generated ID is a flattened hierarchy of controls, you can use the "ends with" selector to find your element.
<input runat="server" id="txtText" />
When rendered, the generated ID becomes something like this (if within a masterpage's content place holder):
<input id="ctl00_contentplaceholder_txtText" />
To find this control:
$("input[id$='txtText']")
Take caution when using this within a repeater.
Try putting it into a variable name:
var txtTestID = '#' + '<%=txtTest.ClientID %>';
$(txtTestID).val();
I'm not sure if the <%= likes being inside double quotes. I've always had mixed behaviors when not using the single quote.
When using ASP.NET 4 and the ClientIDMode is set to “Predictable”, you can predict the ID based on hierarchy. Or set it set to “Static”, so asp.net wont mess it up.
ScottGu's article on it http://weblogs.asp.net/scottgu/archive/2010/03/30/cleaner-html-markup-with-asp-net-4-web-forms-client-ids-vs-2010-and-net-4-0-series.aspx
And this is extremely useful when using external JS file scenarios.
As Darin Dimitrov said in his answer:
<%= txtTest.ClientID %> should work but not in a separate javascript
file where server side scripts do not execute.
The solutions that I could find for those are:
<input runat="server" id="txtTest" value="test" class="txtTest" />
Use class instead of ID
Using class you can retrieve the value anywhere. This is one of the best solutions (usually the best)
var value = $('.txtTest').val();
Use ClientID code in the aspx
You can always call ClientID in the aspx, but if you are working with some kind of structure, this isn't the best solution. I like to use this method when I'm testing something.
var value = $('#<%=txtTest.ClientID%>').val();
You can also use ClientID in a external js file with a workaround. IT'S NOT PRETTY, use only if you really need it. I usually do this when I use Telerik.
In the aspx:
var id = <%=txtTest.ClientID%>;
In the js file:
var value = $('#'+id).val();
Use Control.ClientIDMode Property Static
so the HTML becomes
<input runat="server" id="txtTest" value="test" ClientIDMode="Static" />
and the js can call it as it is named of
var value = $('#txtTest').val();
The problem with this solution is that you need to be very careful to avoid duplicity on the ids of your page. Try never use Static mode in a controller.
As states MSDN:
The ClientID value is set to the value of the ID property. If the
control is a naming container, the control is used as the top of the
hierarchy of naming containers for any controls that it contains.
The link of shaans's answer is a awesome place to check extra information about ClientIDMode.
Cleaner HTML Markup with ASP.NET 4 Web Forms - Client IDs (VS 2010 and .NET 4.0 Series)
To avoid issues with rendered ID's, use a class instead. This won't change during rendering:
function contatoModal() {
//alert("Test");
alert($(".txtTest").val());
}
HTML:
< input runat="server" id="txtTest" value="test" class="txtText" />
Adding a css class to the input and then using this class in jQuery to getting the input element will solve the issue.
I have these lines of code:
<span
class="close-modal"
onclick="#Html.Action("SaveNotes", "CallCenter", new { activityId = item.callIdKey, noteText = "test1" })">
×
</span>
Notes: <br />
<textarea name="paragraph_text" rows="5" style="width:90%">
#item.NoteText
</textarea>
I would like to replace test1 from the noteText route variable and instead change it to whatever the value in the <textarea> tag is.
Is there an elegant way of doing this without writing a giant block of jQuery code?
#Html.Action() renders a partial view as an HTML string during page processing (on the server side). It doesn't exist any more in the markup, once the page is sent to the browser. You can't do what you are trying to do this way. At the very least, I'm sure you don't want to render a partial view inside the onclick event of your <span> tag.
Why not instead use an HTML helper for the <textarea> tag? Then you can get whatever value the user typed into it on the server code. You'll want to make the form post itself back to the server on the close-modal element:
<span class="close-modal" onclick="$('form').submit()">×</span>
<form method="post" action="#Url.Action("SaveNotes", "CallCenter", new { activityId=item.callIdKey }">
Notes: <br />
#Html.TextArea("noteText", item.NoteText, new { rows="5", style="width:90%" })
</form>
This assumes you have jQuery already (a common assumption with ASP.NET). You may not need the <form> tags if you already have a form on your page.
A #gunr2171 notes in the comments, the only way to dynamically update a link once it's been rendered to the browser is via some form of client-side scripting, typically JavaScript. In your case, I'd recommend doing something like this:
<span
class="close-modal"
data-href-template="#Url.Action("SaveNotes", "CallCenter", new {activityId = item.callIdKey, noteText="{note}"})"
>
×
</span>
Note: As #HBlackorby notes in his answer, you shouldn't be using #Html.Action() here; I assume you meant #Url.Action().
This way, your JavaScript has a template (data-href-template) that it can work against with a clearly defined token ({note}) to replace, instead of needing to parse the URL in order to identify where the previously replaced text is. Otherwise, you potentially end up in a scenario where you type e.g. CallCenter into your <textarea /> and it's now an ambiguous reference that you can't just blindly replace. Or, worse, you type 'a' and it's really ambiguous.
If you are already using jQuery on your site, the actual replacement might be done using something along the lines of:
$(document).ready(function () {
$('span.close-modal').click(function() {
var noteInput = $('textarea[name="paragraph_text"]');
var encodedNote = encodeURI(noteInput.text());
var template = $(this).data("href-template");
var targetUrl = template.replace("{note}", encodedNote);
window.location.href = targetUrl;
});
});
You can also do this without jQuery, obviously—and should if you're not already depending on it. The point is to illustrate that this doesn't necessarily need to be a "giant block of jQuery code". In fact, this could be done in just a few lines—and probably should be. I deliberately broke it out into multiple steps and variables for the sake of readability.
I am experiencing odd behavior when data linking an object to a form that led me to re-question what exactly is being data bound?
Basically I have a form that creates new Companies as well as updates them. The actual creation/update is done via ajax, which is why I am using the same form for both purposes. In the case when I have to create a company, everything works as I expect. However when I have to update a company, things don't work like how I expect them to. Please have a look at the following code.
Here is my sample Form HTML:
<div id="result"></div>
<script type="text/x-jsrender" id="CompanyFormTemplate">
<form>
<input type="text" data-link="Company.Name" />
</form>
</script>
Here is my Javascript code:
var app = new CompanyFormContext();
function CompanyFormContext() {
this.Company = {
Name: ''
};
this.setCompany = function (company) {
if (company) {
$.observable(this).setProperty('Company', company);
}
};
};
$(function () {
initPage();
...
if (...) {
// we need to update company information
app.setCompany({ Name: 'Company ABC' });
}
});
function initPage() {
var template = $.templates('#CompanyFormTemplate');
template.link("#result", app);
}
Instead of the form input showing 'Company ABC', it is empty. However if I enter anything in it, then the Company.Name value does change! But while I want the input to data bind to Name property of my Company object, I also want it to be aware of any changes made to the (parent) Company object and update it's data binding to it's Name property accordingly.
So my question is how should I change the way I am writing this code so that I can achieve a data bound both on the root object as well as the property?
The issue you were having was because in your scenario, you have paths like Company.Name for which you want to data-link to changes not only of the leaf property but also to changes involving replacing objects higher up in the path (in this case the Company).
For that you need to use the syntax data-link="Company^Path".
See the section Paths: leaf changes or deep changes in this documentation topic:
http://www.jsviews.com/#observe#deep.
See also the examples such as Example: JsViews with plain objects and array in this topic: http://www.jsviews.com/#explore/objectsorvm.
Here is an update of your jsfiddle, using that syntax: https://jsfiddle.net/msd5oov9/2/.
BTW, FWIW, in your fix using {^{for}} you didn't have to use a second template - you could alternatively have written:
<form class="form-horizontal">
{^{for Company}}
...
<input type="text" data-link="Name" />
{{/for}}
</form>
To respond also to your follow-up question in your comment below, you can associate any 'block' tag with a template. Using tmpl=... on the tag means you have decided to separate what would have been the block content into a separate re-usable template. (A 'partial', if you will). The data context for that template will be the same as it would have been within the block.
So specifically, {{include}} {{if}} and {{else}} tags do not move the data context, but {{for}} and {{props}} do. With custom tags you can decide...
So in your case you could use either {^{for Company tmpl=.../}} or {{include tmpl=.../}} but in the second case your other template that you reference would use <input type="text" data-link="Company^Name" /> rather than <input type="text" data-link="Name" />.
Here are some relevant links:
http://www.jsviews.com/#samples/jsr/composition/tmpl
http://www.jsviews.com/#includetag
http://www.jsviews.com/#fortag
I discovered one way to achieve this. It might seem complex at first but it will make sense once you understand it properly.
(PS: I wish there was a sample like this. I might just blog about it.)
HTML Markup:
<script type="text/x-jsrender" id="CompanyFormTemplate">
<form>
{^{for Company tmpl="#CompanyDetailsTemplate" /}
</form>
</script>
<script type="text/x-jsrender" id="CompanyDetailsTemplate">
<input type="text" data-link="Name" />
</script>
Javascript: No changes needed from code above.
Okay so as I said, the solution might look complicated but it turns out all I really had to do was to set up data binding first on the Company object, and then to it's property objects. I wonder if there is a more elegant solution (i.e. one in which all of this can be achieved in a single template) however this solution ensures that data-binding is happening both on the parent object as well as its' properties.
I have posted a JsFiddle for this solution, so if anyone comes across this problem and wants to understand how this solution would work for their particular problem, they will be able to play with a working solution.
I want to know if it is a good practice to use razor in JavaScript code. For example:
<script type="text/javascript">
var variable = #some.Id
</script>
Or it's better to create hidden value and then take it with JavaScript, like this?
<input type="hidden" id="someId" value"#some.Id" />
<script type="text/javascript">
var variable = $('#someId').val();
</script>
EDIT:
#{
var formVariables = serializer.Serialize(new
{
id = Model.Id,
name = Model.Name,
age = Model.Age
});
<input type="hidden" id="header_variables" value="#formVariables"/>
<script type="text/javascript" src = "/Scipts/..."></script>
}
Is this good solution?
I personally would go with an extension of the 2nd option and create a seperate .js file. The reason being, if you delegate work out to a 3rd party to take care of the jquery/javascript parts of the UI, then they need not have any sight of the backend functionality.
There are a variety of ways to use html5 attributes (i.e. data-attribute='foo') on the inputs which would allow you to 'decorate' your inputs with a cargo of properties which could be parsed inside the external .js file.
A very brief example:
in your view:
<input type='text' id='myId' data-action='#Url.Action("MyAction")' class='myClass' />
in your .js file:
var targetAction = $('#myId').attr('data-action');
this gives complete separation between the .js and the views. It does require a degree of planning of course.
Hope this helps
Razor will be parsed at server-side and replaced by relevant output. Therefore, in my opinion it is totally indifferent, if you place it in Javascript or HTML - at client side only the output value will be visible. Thus, in the above example I would choose the first option (place it directly in JS), since you will not have the otherwise unnecessary hidden input field.
I don't think there is a correct answer to this question; only pros and cons.
Pros of using Razor in Javascript
Script is bound to your view model; so model changes will get picked up automatically, and errors will get caught at compile time.
Cons
Script is mixed with markup, contrary to web design best practices (put script at the bottom so that it will never break your page).
Script cannot be compiled/minified, because, again, it's mixed in with your markup.
Problem: Sometimes you will want to access a component from javascript with
getElementById, but id's are generated dynamically in JSF, so you
need a method of getting an objects id. I answer below on how you can do this.
Original Question:
I want to use some code like below. How can I reference the inputText JSF component in my Javascript?
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<head>
<title>Input Name Page</title>
<script type="javascript" >
function myFunc() {
// how can I get the contents of the inputText component below
alert("Your email address is: " + document.getElementById("emailAddress").value);
}
</script>
</head>
<h:body>
<f:view>
<h:form>
Please enter your email address:<br/>
<h:inputText id="emailAddresses" value="#{emailAddresses.emailAddressesStr}"/>
<h:commandButton onclick="myFunc()" action="results" value="Next"/>
</h:form>
</f:view>
</h:body>
</html>
Update: this post Client Identifiers in JSF2.0 discusses using a technique like:
<script type="javascript" >
function myFunc() {
alert("Your email address is: " + document.getElementById("#{myInptTxtId.clientId}").value);
}
</script>
<h:inputText id="myInptTxtId" value="backingBean.emailAddress"/>
<h:commandButton onclick="myFunc()" action="results" value="Next"/>
Suggesting that the attribute id on the inputText component
creates an object that can be accessed with EL using #{myInptTxtId},
in the above example. The article goes on to state that JSF 2.0 adds
the zero-argument getClientId() method to the UIComponent class.
Thereby allowing the #{myInptTxtId.clientId} construct suggested
above to get the actual generated id of the component.
Though in my tests this doesn't work. Can anyone else confirm/deny.
The answers suggested below suffer from drawback that the above
technique doesn't. So it would be good to know if the above technique
actually works.
You need to use exactly the ID as JSF has assigned in the generated HTML output. Rightclick the page in your webbrowser and choose View Source. That's exactly the HTML code which JS sees (you know, JS runs in webbrowser and intercepts on HTML DOM tree).
Given a
<h:form>
<h:inputText id="emailAddresses" ... />
It'll look something like this:
<form id="j_id0">
<input type="text" id="j_id0:emailAddress" ... />
Where j_id0 is the generated ID of the generated HTML <form> element.
You'd rather give all JSF NamingContainer components a fixed id so that JSF don't autogenerate them. The <h:form> is one of them.
<h:form id="formId">
<h:inputText id="emailAddresses" value="#{emailAddresses.emailAddressesStr}"/>
This way the form won't get an autogenerated ID like j_id0 and the input field will get a fixed ID of formId:emailAddress. You can then just reference it as such in JS.
var input = document.getElementById('formId:emailAddress');
From that point on you can continue using JS code as usual. E.g. getting value via input.value.
See also:
How to select JSF components using jQuery?
Update as per your update: you misunderstood the blog article. The special #{component} reference refers to the current component where the EL expression is been evaluated and this works only inside any of the attributes of the component itself. Whatever you want can also be achieved as follows:
var input = document.getElementById('#{emailAddress.clientId}');
with (note the binding to the view, you should absolutely not bind it to a bean)
<h:inputText binding="#{emailAddress}" />
but that's plain ugly. Better use the following approach wherein you pass the generated HTML DOM element as JavaScript this reference to the function
<h:inputText onclick="show(this)" />
with
function show(input) {
alert(input.value);
}
If you're using jQuery, you can even go a step further by abstracting them using a style class as marker interface
<h:inputText styleClass="someMarkerClass" />
with
$(document).on("click", ".someMarkerClass", function() {
var $input = $(this);
alert($input.val());
});
Answer: So this is the technique I'm happiest with. Doesn't require doing too much weird stuff to figure out the id of a component. Remember the whole point of this is so you can know the id of a component from anywhere on your page, not just from the actual component itself. This is key. I press a button, launch javascript function, and it should be able to access any other component, not just the one that launched it.
This solution doesn't require any 'right-click' and see what the id is. That type of solution is brittle, as the id is dynamically generated and if I change the page I'll have to go through that nonsense each time.
Bind the component to a backing bean.
Reference the bound component wherever you want.
So here is a sample of how that can be done.
Assumptions: I have an *.xhtml page (could be *.jsp) and I have defined a backing bean. I'm also using JSF 2.0.
*.xhtml page
<script>
function myFunc() {
var inputText = document.getElementById("#{backBean.emailAddyInputText.clientId}")
alert("The email address is: " + inputText.value );
}
</script>
<h:inputText binding="#{backBean.emailAddyInputText}"/>
<h:commandButton onclick="myFunc()" action="results" value="Next"/>
BackBean.java
UIInput emailAddyInputText;
Make sure to create your getter/setter for this property too.
Id is dynamically generated, so you should define names for all parent elements to avoid j_id123-like ids.
Note that if you use jQuery to select element - than you should use double slash before colon:
jQuery("my-form-id\\:my-text-input-block\\:my-input-id")
instead of:
jQuery("my-form-id:my-text-input-block:my-input-id")
In case of Richfaces you can use el expression on jsf page:
#{rich:element('native-jsf-input-id')}
to select javascript element, for example:
#{rich:element('native-jsf-input-id')}.value = "Enter something here";
You can view the HTML source when this is generated and see what the id is set to, so you can use that in your JavaScript. As it's in a form it is probably prepending the form id to it.
I know this is not the JSF way but if you want to avoid the ID pain you can set a special CSS class for the selector. Just make sure to use a good name so that when someone reads the class name it is clear that it was used for this purpose.
<h:inputText id="emailAddresses" class="emailAddressesForSelector"...
In your JavaScript:
jQuery('.emailAddressesForSelector');
Of course you would still have to manually manage class name uniqueness.
I do think this is maintainable as long as you do not use this in reusable components. In that case you could generate the class names using a convention.
<h:form id="myform">
<h:inputText id="name" value="#{beanClass.name}"
a:placeholder="Enter Client Title"> </h:inputText>
</h:form>
This is a small example of jsf. Now I will write javascript code to get the value of the above jsf component:
var x = document.getElementById('myform:name').value; //here x will be of string type
var y= parseInt(x,10); //here we converted x into Integer type and can do the
//arithmetic operations as well