Href and mailto links in KnockoutJS
Asked Answered
G

3

16

I'm trying to display a table with links and mailto's in a display template using Knockout. I'm still really new to knock out to I apologize in advance!

This is what my display template was originally:

<script type="text/template" id="customerSearchDisplayTemplate">
    <td class="hiddenId">{0}</td>
    <td><a href="/wrenchsciencewebadmin2/UserManager/Customer/CustomerEditor.aspx?CustomerID={1}">{1}</a></td>
    <td><a href="mailto:{2}">{2}</a></td>
    <td>{3}</td>
    <td>{4}</td>
    <td>{5}</td>
    <td>{6}</td>     
    <td>{7}</td>
    <td><a href="/wrenchsciencewebadmin2/Common/PopupWindows/CustomerNotes.aspx?customerid={8}">{8}</a></td>                     
</script>

and this is what I have so far, minus the mailto AND links:

<script type="text/template" id="customerSearchDisplayTemplate">
    <tr>
        <td class = "hiddenId"><span data-bind="text: customerSearchID"/></td> 
        <td><span data-bind="text: fullName" /></td>
        <td><span data-bind="text: primaryEmail" /></td>
        <td><span data-bind="text: secondaryEmail" /></td>
        <td><span data-bind="text: homePhone" /></td>
        <td><span data-bind="text: workPhone" /></td>
        <td><span data-bind="text: mobilePhone" /></td>
        <td><span data-bind="text: lastLogonDate" /></td>
        <td><span data-bind="text: wsNotes" /></td>            
    </tr>
</script>
Gigigigli answered 20/8, 2013 at 19:55 Comment(0)
S
24

Using the attr and text properties in the data-bind attribute like so:

<script type="text/template" id="customerSearchDisplayTemplate">
    <tr>
        <td class = "hiddenId"><span data-bind="text: customerSearchID"/></td> 
        <td><span data-bind="text: fullName" /></td>
        <td>
            <span>
                <a data-bind="text: primaryEmail, 
                              attr: {href: 'mailto:'+primaryEmail()}" />
            <span/>
        </td>
        <td>
            <span>
                <a data-bind="text: secondaryEmail, 
                              attr: {href: 'mailto:'+secondaryEmail()}" />
            <span/>
        </td>
        <td><span data-bind="text: homePhone" /></td>
        <td><span data-bind="text: workPhone" /></td>
        <td><span data-bind="text: mobilePhone" /></td>
        <td><span data-bind="text: lastLogonDate" /></td>
        <td><span data-bind="text: wsNotes" /></td>            
    </tr>
</script>
Sharpe answered 20/8, 2013 at 20:1 Comment(1)
User 2048714 is correct, you need to ensure that you access the value using the function.Shopper
G
4

Be sure to access the emails via the function syntax when binding the attr i.e. primaryEmail() otherwise it will return the function definitions rather than the value.

<div data-bind="template: { name : 'customerSearchDisplayTemplate'}"></div>

<script type="text/template" id="customerSearchDisplayTemplate">
    <tr>
        <td class="hiddenId">
            <span data-bind="text: customerSearchID"/>
        </td> 
        <td><span data-bind="text: fullName" /></td>
        <td>
            <a data-bind="text: primaryEmail, 
                          attr: { href : 'mailto:'+primaryEmail() }" />
        </td>
        <td>
            <a data-bind="text: secondaryEmail, 
                          attr: { href : 'mailto:'+secondaryEmail() }"/>
        </td>
        <td><span data-bind="text: homePhone" /></td>
        <td><span data-bind="text: workPhone" /></td>
        <td><span data-bind="text: mobilePhone" /></td>
        <td><span data-bind="text: lastLogonDate" /></td>
        <td><span data-bind="text: wsNotes" /></td>            
    </tr>
</script>

Example: http://jsfiddle.net/lifetimelearner/yr7SP/2/

Gan answered 20/8, 2013 at 20:20 Comment(0)
F
3

If you want to go MVVM all the way, it's best to keep your View as dumb as possible:

<a data-bind="text: primaryEmail, attr: {href: primaryEmailMailtoLink}"></a>

Then make a computed observable on your view model:

var ViewModel = function() {
    var self = this;

    // Observable property:
    self.primaryEmail = ko.observable('[email protected]');

    // Dependent observable:
    self.primaryEmailMailtoLink = ko.computed(function() {
            return 'mailto: ' + self.primaryEmail();
    };

    // Etc. (rest of your view model)
}
Florrieflorry answered 20/8, 2013 at 20:37 Comment(5)
I disagree that this is "MVVM all the way." MVVM doesn't mean stupid views, it means separated views and viewmodels. This is actually tying the viewmodel to the view by brining in HTML link knowledge. The fact that the email address is going to be used by a link is knowledge the viewmodel shouldn't have, but which the view should have. You could make a binding handler for the mailto link, but I think that's unncesarry. The view displaying an email in a mailto link is view behavior, and should be left there.Iconoduly
@Tyrsius You make a valid point. However, I still think the "mailto" is not an aspect of the View, but an aspect of your Model as it encapsulates business logic. Consider the situation where you want to add a CC or use another advanced mailto feature. If you have the logic in your Model it'll be easy to change, only in one place: the computed observable. If you've done the string concatenation in your view you'll have to update every single place you've used a mailto link.Florrieflorry
Regardless of taste, the code's a valid way to solve the OP's problem, by the way ;-)Florrieflorry
I never said it was invalid... just that I disagreed with your statement. You make a good point about mailto having features though, and I think a binding handler would be an appropriate way to include those, by passing options to it. I still don't think that its business logic. The person you are mailing has an emailaddress, but the person doesn't have a mailto link; it's not a property of the model, and it isn't a function either. It's purely a way to show the email address as a link that can be clicked on.Iconoduly
@Tyrsius Apologies, the "validness" comment wasn't aimed specifically at you, just at whoever clicked the "This answer is not useful" button.Florrieflorry

© 2022 - 2024 — McMap. All rights reserved.