How to spit out a JavaScript variable (type array) from Custom Control - asp.net

I want to spit out a JS variable array like so from my custom control:
var myArray = [5410, 8362, 6638, 6758, 7795]
caveat is that I want it to also be unique to this control as this control will spit out more JavaScript that will utilize myArray. So I envision something like:
var [control'sID]myArray = [5410, 8362, 6638, 6758, 7795]
and then somehow the rest of the JavaScript that is spit out can reference this somehow where needed in the JS code. I've got certain methods in the other JavaScript that is being spit out that is using myArray.

You can use ClientID
C# Example:
Response.Write("var " + this.ClientID + "myArray = [5410, 8362, 6638, 6758, 7795];");
VB Example:
Response.Write("var " & Me.ClientID & "myArray = [5410, 8362, 6638, 6758, 7795];")

I think you want to generate a javascript array from your custom control, and you want to access it from your main library,
You can use your control's ClientID property to make your arrays unique.
And you can define a global array to keep the array's names to access them from your rest of the client scripts.
EDIT :
I just look at the RegisterExpandoAttribute method, it's an interesting method, I have never heard that before. In this example it looks like it you can add custom attributes to your control.
So you can use it in your custom control like that :
Just add a custom attribute that has your array items with comma separated. and when accessing the custom attribute, simply split them by comma. I think this will work for your question.
At your custom control :
Page.ClientScript.RegisterExpandoAttribute(this.ClientID
, "myArray", "1,2,3,4");
At client side, get your array like that :
var myArray =
document.getElementById('<%= this.ClientID %>').getAttribute("myArray")).split(',');

Related

SDL Tridion GetListKeywords using Anquilla Framework

I'm writing a GUI extension and using the Anquilla framework to get a list of Keywords within a Category. I'm obtaining an XML document for the list of keywords then working with that document within my extension.
My problem is that the returned XML doesn't contain the Keyword's 'Description' value. I have the Title and Key etc.
My original code looks like this:
var category = $models.getItem("CATEGORYTCMID:);
var list = category.getListKeywords();
list.getXml();
A typical node returned is this:
<tcm:Item ID="tcm:4-1749-1024"
Type="1024" Title="rate_one" Lock="0" IsRoot="true"
Modified="2012-12-17T23:01:59" FromPub="010 Schema"
Key="rate_one_value" IsAbstract="false"
CategoryTitle="TagSelector"
CategoryID="tcm:4-469-512" Icon="T1024L0P0"
Allow="268560384" Deny="96" IsNew="false"
Managed="1024"/></tcm:ListKeywords>
So I've tried using a Filter to give me additional column information:
var filter = new Tridion.ContentManager.ListFilter();
filter.columns = Tridion.Constants.ColumnFilter.EXTENDED;
var list = category.getListKeywords(filter);
Unfortunately this only gives the additional XML attributes:
IsShared="true" IsLocalized="false"
I'd really like the description value to be part of this XML without having to create a Keyword object from the XML. Is such a thing possible?
cough any ideas? cough
I'm afraid you'll have to load the Keyword itself to get the Description.
It's not used in any lists, so it's not returned in the XML.
You could always create a List Extender to add this information to the list, but try to be smart about it since this extender will execute everytime a GetList is called.
Won't save you from having to open every keyword in the list, but you'll be doing it server-side (with Core Service/NetTcp for instance) which will probably be easier and faster than opening each keyword with Anguilla.
In this instance I only need the one keyword, so I simply get it from the CMS. Getting an object in Anguilla is a bit weird, here's the code:
In your main code area:
var selectedKy = $models.getItem("TcmUriOfKeywordHere");
if (selectedKy.isLoaded()) {
p.selectedKy = selectedKy;
this.onselectedKyLoaded();
} else {
$evt.addEventHandler(selectedKy, "load", this.onselectedKyLoaded);
selectedKy.load();
}
It's worth noting how I store the keyword in the properties of the item, so I can obtain it in the onselectedKyLoaded function
The function called once the item is loaded
ContentBloom.ExampleGuiExtension.prototype.onselectedKyLoaded = function (event) {
var p = this.properties;
var selectedDescription = p.selectedKy.getDescription();
// do what you need to do with the description :)
};
I resolved this, thanks to the answer here: https://stackoverflow.com/a/12805939/1221032 - Cheers Nuno :)

Request.Form "Collection is only readonly" when trying to set text box content

Saving the values in the Lists & works fine.
abc= (ABC)(Session["xml"]);
string ctrlStr = String.Empty;
foreach (string ctl in Page.Request.Form)
{
if (ctl.Contains("something"))
{
ctrlStr = ctl.ToString();
abc.student[0].marks[j].science.something.Value = Convert.ToDecimal(Request.Form[ctrlStr]);
}
Want to retrieve the values from the saved object when I click on edit button back on the respective dynamic textboxes....
foreach (string ctl in Page.Request.Form)
{
if (ctl.Contains("studentname"))
{
ctrlStr = ctl.ToString();
(Request.Form[ctrlStr]) = abc.student[0].marks[x].science.studentname.ToString();---Gives an error stating the collection is only readonly
}
}
Request.Form — like the Request object generally — is read-only, reflecting the fact that, by the time you are responding to a request, the request itself cannot be changed. ASP.NET uses the values from the form POST to create server controls on the Page, and these allow you to control the values of the input and other form elements that are written to the Response object.
In your case, the TextBox controls are being generated dynamically, so they are not automatically bound to form values — hence your problem. You will need to keep references to the controls when they are created (or find them afterwards using the FindControl() method) and set their Text property.
(original answer follows)
The Controls collection becomes read-only at a certain point in the construction of the page. You have to do manipulation before that point. I don't remember offhand when it is, but you're safe with OnLoad through OnPreRender.
Where is your code firing from?
Update: Okay, I see what you're trying to do. This will be easiest if you're dealing with server-side controls (that is, controls generated by ASP.NET. That would look like this in your aspx (or ascx):
<asp:TextBox runat="server" ID="studentname"/>
Then you could update the value like this:
abc = (ABC)(Session["xml"]);
studentname.Text = abc.student[0].marks[j].science.something.Value.ToString();
That will set the value of the studentname text box automatically without needing to search through all of the Request.Form items. (Assuming you set j somewhere... I don't know the context for that.)
I can't tell for sure from your code, but it looks like you may just have a "plan HTML" input, which would look more like this:
<input type="text" name="studentname"/>
In that case, there is no simple way to update the value from your page's code, so I'd start by making sure that you're using server-side controls.
You can set the Request.Form values with reflection:
Request.Form.GetType().BaseType.BaseType.GetField("_readOnly", BindingFlags.NonPublic | BindingFlags.Instance)
.SetValue(Request.Form, false);
Request.Form["foo"] = "bar";
What you are trying to achieve?
The Form collection retrieves the values of form elements posted to the HTTP request body, with a form using the POST method. - http://msdn.microsoft.com/en-us/library/ms525985(v=vs.90).aspx

ASP.Net Auto-populate field based on other fields

I've just moved to web development and need to know how i can implement below requirement using asp.net and vb.net.
I have three fields in a form which are filled by users. Based on these three values, i need to auto-populate the 4th field. I have planned to implement this in the following way
Write a separate class file with a function to calculate the possible values for the 4th fields based on 1st 3 inputs. This function can return some where between 1-10 values. So I've decided to use drop-down for 4th field, and allow users to select the appropriate value.
Call the above function in onchange function of 3rd field and take and use the return values to populate the 4th field. I'm planning to get the return values in array field.(Does this need a post back?)
Please let me know how if there is better way to implement this.
Thanks.
You may want to consider doing this with Javascript. You could read and control the fields pretty easily with pure Javascript, or using a nice library like jQuery (my favorite). If you did it this way, no post-back would be required and the 4th field would update immediately. (Nice for your users)
You can also do it with ASP.NET for the most part. "onchange" in ASP.NET still requires Javascript as far as I know, it just does some of it for you. A post-back will definitely happen when you change something.
You need javascript or to set autopostback=true on your form elements.
From a user perspective the best thing is to use javascript to populate the field for display, BUT when the form is submitted use your backend function to validate it. This will make sure the user didn't change the value.
An easy way is to use jQuery for the UI (that way you don't have to worry about long winded javascript and deal with browser compatibility as it's already taken care of for you) and have it call to the server for the data. For the server, your easiest route is to return JSON for looping values.
Include your jQuery:
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js"></script>
Then add in a handle for the JavaScript:
<script type="text/javascript">
function autoPopulate() {
var value1 = $('#ddl1').val();
var value2 = $('#ddl2').val();
var value3 = $('#ddl3').val();
var url = 'path/to/your/file.aspx?value1=' + value1 + '&value2=' + value2 + '&value3=' + value3;
$.getJSON(url, function(data) {
data == null ? return false : data = eval(data);
var ddl = $('#ddl4')[0];
for (i = 0; i < data.length; i++) {
var option = new Option(data[i][0], data[i][1]);
if ($.browser.msie) {
ddl.add(option);
} else {
ddl.add(option, null);
}
}
}
}
</script>
(Yes, I know I used a native loop but I'm little lazy here today :) )
Now, for your server side code you'll want your code your page to return data in the format of:
[['value1','text1'],['value2','text2'],['value3','value3']]
so something like:
<script type="vb" runat="server">
Private Sub Page_Init()
// get your data
// loop through it and add in values
// ex.
Dim result As String = "[" //start multi-dimensional array
For Each Item As String In data
result += String.Format("['{0}','{1}'],", _value, _text)
Next
result = result.SubString(0, result.Length - 1) // removes trailing comma
result += "]" // closes off m-array
Response.Write(result)
Response.Flush()
End Sub
</script>

dynamically generate ComboBox name

I have a script that parses some complex XML. When the XML element is of a certain type, it generates a comboBox using the XML element's children to populate the box. I then want to check all of the values of the all the generated ComboBoxes against their correct answers (which is also info stored in the XML file). When creating the ComboBoxes, I added an "id" property. However, it seems that I cannot them use:
dynamicQuestion.id.selectedItem.labelField
to check the answers. However, I am able to get the labelField if I know the variable name used to create the ComboBox.
dynamicQuestion.selectedItem.labelField
This indicates (to me) that I need to dynamically generate the variable name as I'm creating new instances of the ComboBox. But how do I dynamically generate a variable name? If I use
var thisBox:String = "box"+boxCount;
var newBox:ComboBox = thisBox as ComboBox;
I get an implicit coercion error. I also tried changing the creation statement to a function that accepted an argument, "thisBox," but this didn't work either. Conceptually, this seems quite simple, but I'm having a hard time putting it to practice. It seems that the comboBox's id is what is generated by created the box using script (e.g., var thisBox). How do I dynamically generate this name?
Use an array as Stefan suggested. If you must use string identifiers, you can create an object and use it as an associative array.
var combos:Object = {};
var boxCount:Number = 1;
var thisBox:String = "box"+boxCount;
//you can store comboboxes in the object using the following syntax
combos[thisBox] = new ComboBox();
//or
combos.box2 = new ComboBox();
//or
combos["box3"] = new ComboBox();
trace(combos.box1.selectedItem.labelField);
trace(combos.box2.selectedItem.labelField);
trace(combos.box3.selectedItem.labelField);
Why don't you store all your dynamically created combo boxes in an array? When you want to evaluate them you iterate over the array and access selectedItem.labelField.

getting client id of a control from variable

I want the client id of an asp.net textbox control(txtTest) in javascript.But the problem here is the control id comes from a variable as shown below
var testName = 'txtTest';
var testCntrl = document.getElementById('<%=' + testName + '.ClientID %>');
But its throwing
CS1012: Too many characters in
character literal
Can any one please help....
Try this:
document.getElementById('<%=txtTest.ClientID %>');
Or more along the lines of your original example:
var testName = '<%=txtTest.ClientID %>';
var testCntrl = document.getElementById(testName);
It appears from your example that you have managed to confuse yourself over what is server side and what is client side code.
<%= aspControlID.ClientID %> is a server side control, but you are trying to pass a clientside variable name to it. By the time testName is set equal to 'txtTest' its too late, you're already on the client.
There are a number of alternatives to get the server side ClientIDs as Rick Stahl discusses.
1) You can pre-load all the control IDs that you know you're going to need like this, they query them (he uses jquery) when you need their elements.
var ids = {
txtSymbol: "#<%= txtSymbol.ClientID %>",
PageContent: "#<%= PageContainer.ClientID %>"
}
This can also be written:
var txtSymbol = document.getElementById('<%= txtSymbol.ClientID %>');
var txtBlah = document.getElementById('<%= txtBlah.ClientID %>');
2) Or, he wrote a function that will get a control for you from the clientside
function $$(id, context) {
var el = $("#" + id, context);
if (el.length < 1)
el = $("[id$=_" + id + "]", context);
return el;
}
Be aware that there are some serious caveats. This relies on JQuery, so be sure to include that library and use it like this $$('myASPControlID').val('new val'); The catch is that if you have any controls that create other controls, like listviews, repeaters, gridviews etc. Then finding a single instance of a child control will take some strategy. In that situation, this tool will only get the first instance of a repeated control.
Still, the function provides a way to solve this problem by allowing you to specify a containing element in the second field.
EDIT
Hey L G, if you really need to pass your variable from the client side, then just add the second function and a link to the JQuery library. Then you can get your control with this simple code:
var testName = 'txtTest';
var testCntrl = $$(testName);
If it is C# code (which I assume, given the compilation error), you need to surround strings with " instead of '.
' is used for char values, that can contain only one character (or two if it is an escaped one, such as '\n').
But I don't really get the connection between the compilation error and the code, since the C# compiler should not bother about the javascript code...

Resources