Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Live-bound dynamic attributes don't get updated properly if they don't exist on initial execution #157

Closed
ghost opened this issue Nov 16, 2012 · 13 comments
Assignees
Labels
Milestone

Comments

@ghost
Copy link

ghost commented Nov 16, 2012

This was discussed and fixed for EJS templates:

https://forum.javascriptmvc.com/topic/live-binding-an-image

But it doesn't work with Mustache templates. Check the following fiddle:

http://jsfiddle.net/donejs/4SmxJ/2/

It gives the !! error

@amcdnl
Copy link
Contributor

amcdnl commented Nov 16, 2012

Does this happen in EJS too?

@daffl
Copy link
Contributor

daffl commented Nov 16, 2012

Yes, but the solution for EJS looked like this:

<img <%= this.attr('image') ? "src='" + this.image + "'" : "" %> alt="An image" />

What I think should be the equivalent in Mustache doesn't work the same though:

<img {{#image}}src="{{image}}"{{/image}} alt="An image" />

Should we just add a special case for src attributes in the view renderer?

@ghost ghost assigned andykant Nov 16, 2012
@andykant
Copy link
Contributor

I'll look into why this is happening, but in the meantime, here's a workaround:

<img {{#image}}src="{{.}}"{{/image}} alt="An image" />

@ghost
Copy link
Author

ghost commented Nov 16, 2012

It does work with your workaround, thanks !

andykant added a commit that referenced this issue Jan 28, 2013
Observe properties added after initialization do not live update
properly in attributes
@andykant
Copy link
Contributor

This ended up not being an issue with images specifically. From what I've narrowed it down to, can/view/render fails to properly set up live binding for observe properties if it is being set to a node's attribute (in this case src) if the property doesn't exist when the template is originally rendered. This occurs with both Mustache and EJS, so I added tests for both in the live-bind-observe-attr-157 branch.

This works:

data = new can.Observe({
        user: 'Tina Fey',
        messages: 0,
        image: 'some-value'
    })
data.attr('image', 'http://farm8.staticflickr.com/7102/6999583228_99302b91ac_n.jpg');

This doesn't:

data = new can.Observe({
        user: 'Tina Fey',
        messages: 0
    })
data.attr('image', 'http://farm8.staticflickr.com/7102/6999583228_99302b91ac_n.jpg');

@andykant
Copy link
Contributor

I was hoping #153's fix would knock this one out too as they seemed very related. No such luck but hopefully the solution with that bug will help with this one.

andykant added a commit that referenced this issue Mar 20, 2013
Observe properties added after initialization do not live update
properly in attributes
andykant added a commit that referenced this issue Mar 20, 2013
andykant added a commit that referenced this issue Mar 20, 2013
@andykant
Copy link
Contributor

What seems to be happening is that can.view.pending() doesn't update attributes when the attribute is being set in a nested block. The pending hookup for the nested block is created but not executed.

This works:

// <img src="<%== this.attr("image") %>" alt="An image" />
var ___v1ew = [];
___v1ew.push("<img src=\"");
___v1ew.push(can.view.txt(0, 'img', 'src', this, function() {
    return this.attr("image")
}));
___v1ew.push("\" alt=\"An image\" ", can.view.pending(), "/>");
___v1ew.push(can.view.txt(1, 'undefined', 0, this, function() {
    return this.attr("image")
}));;

So does this:

// <img src="<% { %><%== this.attr("image") %><% } %>" alt="An image" />
var ___v1ew = [];
___v1ew.push("<img src=\"");
___v1ew.push(can.view.txt(0, 'img', 'src', this, function() {
    var ___v1ew = []; {
        ___v1ew.push(can.view.txt(0, 'img', 'src', this, function() {
            return this.attr("image")
        }));
    };
    return ___v1ew.join('')
}));
___v1ew.push("\" alt=\"An image\" ", can.view.pending(), "/>");;

But this doesn't:

// <img <% { %>src="<%== this.attr("image") %>"<% } %> alt="An image" />
var ___v1ew = [];
___v1ew.push("<img ");
___v1ew.push(can.view.txt(0, 'img', 1, this, function() {
    var ___v1ew = []; {
        ___v1ew.push("src=\"");
        // The pending hookup this generates doesn't get created
        // until after the can.view.pending() later on.
        ___v1ew.push(can.view.txt(0, 'img', 'src', this, function() {
            return this.attr("image")
        }));
        ___v1ew.push("\"");
    };
    return ___v1ew.join('')
}));
___v1ew.push(" alt=\"An image\" ", can.view.pending(), "/>");
___v1ew.push(can.view.txt(1, 'undefined', 0, this, function() {
    return this.attr("image")
}));;

@andykant
Copy link
Contributor

After some more research, we need a way to ensure that the can.view.txt calls are still initially executed (just not pushed into ___v1ew) regardless of potential surrounding logic. This might require significant changes to view/render and view/scanner.

@andykant
Copy link
Contributor

Renamed the title of this issue to better describe it and prevent more duplicates.

@justinbmeyer
Copy link
Contributor

So, I made my own test and imported andy's and this is working in 1.2:

    var template = can.view.mustache('<img {{#image}}src="{{.}}"{{/image}} alt="An image" />'),
        data = new can.Map({
            image: null
        }),
        url = "http://canjs.us/scripts/static/img/canjs_logo_yellow_small.png";

    var frag = template(data),
        img = frag.childNodes[0];

    equal( img.hasAttribute('src'), false, "there is no src");

    data.attr("image",url)
    equal(img.hasAttribute('src'), true, 'Image should have src')
    equal( img.src, url, "images src is correct" );

This passes. So I'm closing this issue?

@justinbmeyer
Copy link
Contributor

We can open another issue that allows you to write this src="{image}", but this doesn't seem to be the focus of this issue.

@daffl daffl reopened this Oct 8, 2013
@daffl
Copy link
Contributor

daffl commented Oct 8, 2013

This was what this issue is about. @andykant combined several similar issues into this one.

hobbyquaker added a commit to hobbyquaker/DashUI that referenced this issue Mar 28, 2014
hobbyquaker added a commit to hobbyquaker/DashUI that referenced this issue Mar 28, 2014
hobbyquaker added a commit to hobbyquaker/DashUI that referenced this issue Mar 28, 2014
hobbyquaker added a commit to hobbyquaker/DashUI that referenced this issue Mar 28, 2014
hobbyquaker added a commit to hobbyquaker/DashUI that referenced this issue Mar 28, 2014
hobbyquaker added a commit to hobbyquaker/DashUI that referenced this issue Mar 28, 2014
hobbyquaker added a commit to hobbyquaker/DashUI that referenced this issue Mar 28, 2014
hobbyquaker added a commit to hobbyquaker/DashUI that referenced this issue Mar 28, 2014
hobbyquaker added a commit to hobbyquaker/DashUI that referenced this issue Mar 28, 2014
hobbyquaker added a commit to hobbyquaker/DashUI that referenced this issue Mar 28, 2014
hobbyquaker added a commit to hobbyquaker/DashUI that referenced this issue Mar 28, 2014
@sarathgalimelu
Copy link

sarathgalimelu commented Jul 13, 2017

Hello @andykant I was trying to use the img src as you mentioned in the workaround

<img {{#image}}src="{{.}}"{{/image}} alt="An image" />

This is my code what I have been trying to set the image src using a dataURI string to the template. But the src tag itself is not appended to the code after rendering the template. Can you help in this. Tried different combinations but didn't help. Working when the img src is a tag in my code.
Here is my code below and the version that I am using is 2.0

<a href="https://www.google.com/" style="font-family: 'Helvetica Neue', sans-serif; color: rgb(58, 139, 187); font-weight: normal; text-decoration: underline;" class="" target="_blank">
<img class="photo" width="200" src="{{ logoImage }}" id="headerImage" alt="Test Google" style="border: 0px; height: auto; line-height: 34px; outline: none; max-width: 600px !important;" />
</a>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants