views:

711

answers:

2

I am trying to create a simple ajax grid that allows me to add and remove rows and also edit some of the columns and have others columns calculated directly based on the input in the others. I thought this would be a nice oppurtunity to play with asp.net ajax 4.0 and the client templates. It works pretty ok but I can't seem to find a way to bind my json data to a . How can I do this?

A normal template looks like this

<div id="authorsTemplate" style="visibility:hidden;display:none;"> 
    <ul> 
        <li>First Name: {{ FirstName }}</li> 
        <li>Last Name: {{LastName}}</li> 
        <li>Url: <a href="{{Url}}">{{Url}}</a></li> 
    </ul> 
</div>

How would I use the data bind syntax with a dropdown

<select id="">
  <option value="1">1</option>
  <option value="2">2</option>
</select>

EDIT: If the select tag had a value attribute the obvious solution would be. Edit2: The syntax below was actually the solution, Thx Roatin, I had no idea the select actually had a value attribute.

<select id="" value="{binding nr}">
    <option value="1">1</option>
    <option value="2">2</option>
</select>

I could maybe use custom javascript to set the selected option but the point is a live binding to my json object the same way you bind to the value of a input tag

A: 

I have not actually tried this but it looks like any of these three links blog post could help. All the examples show binding to lists of data. Maybe something like this:

* Sample not tested my VS 2010 comp is busted and is closely derived from the third link *

var sampleData = [
    { Value: "1", Text: "1" },
    { Value: "2", Text: "2" },
];
var select = "1";

<select id="list" class="sys-template" 
    sys:attach="dataview" 
    dataview:data="{{ sampleData }}">
    <option value="{{ Value }}">{{ Text }}</option>
</select>

Then to select the value you want (done the brute force way)

var list = document.getElementById( "list");
foreach ( var option in list.options)
{
    if( option.value == select)
    {
        option.selected = true;
        break;
    }
}

Or tweak the template to include a binding for a 'selected' option. ( Again not tested, you might not be able to perform Selected === true)

var sampleData = [
    { Value: "1", Text: "1", Selected: true },
    { Value: "2", Text: "2" },
];
var select = "1";

<select id="list" class="sys-template" 
    sys:attach="dataview" 
    dataview:data="{{ sampleData }}">
    <option value="{{ Value }}" selected="{{ Selected === true }}">{{ Text }}</option>
</select>
smaclell
Thx, but its not quite what I was looking for. I do not want to populate the dropdown, it is already populated. I want to be able to use the client template binding syntax to get the value from my json object and set the selected element. It could be that I am looking at the problem from the wrong angle though. It would have been easy if the <select> tag had a value attribute
TT
You can always use JS to set the selected index of the select element. Something like sel.selectedIndex and you can get the index you need by looking through the options array. Later I will add a code example in the answer.
smaclell
I updated my question to clarify
TT
Do these extra clarifications help? I not can you clarify how you would want it to set the selection. Are you using any JS libraries?
smaclell
+3  A: 

I do not want to populate the dropdown, it is already populated. I want to be able to use the client template binding syntax to get the value from my json object and set the selected element.

In fact, select DOM elements do have a value property (but not exposed as an attribute in the markup). Setting it is equivalent to (and faster than) iterating the child <option>s and setting the selectedIndex to the found option index of the option that has a matching value.

Anyway, here's how to bind to it directly with Sys.Binding (complete test case):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
<html xmlns="http://www.w3.org/1999/xhtml"&gt;
<head>
    <style type="text/css">.sys-template {display:none}</style>
    <script src="MicrosoftAjax.debug.js"></script>
    <script src="MicrosoftAjaxTemplates.debug.js"></script>

    <script type="text/javascript">
    var dataItem = { Foo: '3' };
    function pageLoad()
    {
        $create(Sys.Binding, {
            target: $get("list"),
            targetProperty: 'value',
            source: dataItem,
            path: 'Foo',
            mode: Sys.BindingMode.twoWay
        });
    }
    </script>
</head>
<body>
  <select id="list">
    <option value="1">One</option>
    <option value="2">Two</option>
    <option value="3">Three</option>
  </select>
</body>
</html>

Here is how to do the same thing declaratively, if you prefer:

<body xmlns:sys="javascript:Sys"
      xmlns:binding="javascript:Sys.Binding"
      sys:activate="*">

  <select id="list"
    sys:attach="binding"
    binding:target="{{ $get('list') }}"
    binding:targetproperty="value"
    binding:source="{{ dataItem }}"
    binding:path="Foo">
    <option value="1">One</option>
    <option value="2">Two</option>
    <option value="3">Three</option>
  </select>

(and of course get rid of the pageLoad JavaScript stuff...)

Both examples set up two-way binding to the dataItem object. You can see when the page loads, the third <option> is selected as that is the option with a value matching dataItem.Foo. When you select a different item from the drop-down, dataItem.Foo updates with the new value selected.

Hope that helps!

Roatin Marth
ps I'm using ASP.NET AJAX Preview 5.
Roatin Marth
Thx, just what i was looking for, i'l lgive it a try later
TT