I was using the setAttribute method and noticed that if I use it consecutively, only the first time I use it the DOM elements changes, whereas the second time it doesn't work. And i don't understand why.
example, if i write this:
grid.setAttribute("style", `grid-template-rows:repeat(auto-fill,${width/size}px);`);
grid.setAttribute("style", `grid-template-columns:repeat(auto-fill,${width/size}px);`);
only the grid-template-rows changes.
But if i put it all in one line like this:
grid.setAttribute("style", `grid-template-columns:repeat(auto-fill,${width/size}px); grid-template-rows:repeat(auto-fill,${width/size}px);`);
then both values change, which gives the desired outcome.
Can anyone explain me why the first instance doesn't work?
Related
I've got a simple example demonstrating what I'm seeing: https://stackblitz.com/edit/lit-element-example-3pdnwk?file=index.js.
Basically when the first child element renders, the text property is set correctly. However on the second render, the text property is undefined first and then updated to be the correct value.
This breaks being able to depend on _firstRendered() to have the correct values assigned to the properties.
Am I doing something really off here?
Update: Here is a better example using a similar method provided in the lit-html documentation: https://stackblitz.com/edit/lit-element-issue?file=index.js
Am I doing something really off here?
maybe? :) Hopefully you can help me to understand why you chose your implementation and I can look into it further.
The part I'm stuck on is why you create and replace the child element inside the parent element like this:
this._child = html`<child-element text="${text1}"></child-element>`;
From what I understand so far, that code uses a lit-html helper function to create a lit-html TemplateResult. You then replace it with another one in the timeout callback:
this._child = html`<child-element text="${text2}"></child-element>`;
So instead of just re-drawing only the stuff that changed (a string), your code creates a new TemplateResult and redraws that. This also calls the child element constructor again and causes the text node to go undefined for a moment as you noted. Here is console output added to your impl to show when the constructor and render functions get called for parent and child:
https://stackblitz.com/edit/lit-element-example-ftlbz7?file=index.js
From inspecting the DOM tree, your example produces this DOM structure:
<parent-element>
#shadow-root
<div>
<child-element>
#shadow-root
<div>
Suppose I need to produce that same DOM structure and have the same text node update in response to the timeout callback, I would probably handle it in the parent render function:
_render({ parenttext }) {
return html`<div><child-element text="${parenttext}"></child-element></div>`;
}
which ensures that the child constructor is only called once, and only the data that actually changes gets redrawn.
If I understand correctly, that's how lit-element is designed to be used (expressing an app or element's render as a function of its data). That way we can rely on the browser to just redraw any changes to the data. This should theoretically be faster (altho I haven't tested it).
Code sample here:
https://stackblitz.com/edit/lit-element-example-exrlxw?file=parent-element.js
Lmk what I'm missing from your tests and I can look into it more.
Edited to add:
I noticed that overriding _shouldRender to prevent the element from rendering with undefined props prevented the element from rendering with undefined props, but it didn't fix _firstRendered, which was still firing when props were undefined.
_firstRendered, unlike _didRender, is not specifically called as a result of _render; it is called from the ready() callback, which is inherited from Polymer's properties-changed mixin. In Polymer, ready() fires when the element is added to the DOM. I thought properties should be initialized by then, so this is still pretty weird.
Anyways, this means it is possible to create an element that never renders (i.e _shouldRender always returns false), but _firstRendered still fires. Lol. Sample: https://stackblitz.com/edit/lit-element-first-rendered?file=index.js.
I'm not honestly sure what to make of any of this. I'll raise an issue on the lit-element github when I've read a few more things from the documentation (or you can, if you get there first).
This is no longer an issue as of 0.6.0-dev.5
I have problem with nested loops. Please take a look on the fiddle below:
http://jsfiddle.net/7znfmp9o/
I want each section to get parallax effect however something strange is going on here. .each() code is applied only for last element within the loop.
Changing this line:
$bgElm = $(this).find('.swiper-slide-bg, .mk-section-video')
into this:
$bgElm = $('.parallax-true').eq(0).find('.swiper-slide-bg, .mk-section-video')
runs the snippet on desired section, however iteration on .eq(i) doesn't work either, even within closure:
(function(i){ ... })(i);
What am I missing here? Thx for your help
The problem is due to this line:
$bgElm = $(this).find('.swiper-slide-bg'),
You are setting the contents of this internal variable every time the first forEach occurs. When the event is raised the value of this is the last element in the forEach loop. You should move these variables outside of the forEach loop and append elements into it. Then once the event is raised for loop on the elements within this variable.
I put together a VERY crude implementation of what I am proposing. While it works, you should reorganize the data structures and give proper naming to help describe your intentions. For instance, $bgElm is a poor variable choice for a variable describing the set of parallax-ed elements.
http://jsfiddle.net/myqswjnt/
I'm using inheritance to implmenet a reuseable forms app.
Expression parameter can be dependent on one or more other numeric/constant ot other expression parameters (the relation is many to many so heirarchy wont work here). Once all my dependent parameters evaluated them self (calcualted if expression or validated if user input) I can now calculate my self.
I'm looking for a way to subscribe to my siblings but the problem is that during creation the sibling does not neccasarily exists yet.
I set up a small example on this Fiddle.
To see this not working in action lets change the values from the console
d.parameters()[0].value(10) // expecting parameter C to sum up to 20.
d.parameters()[2].value() // Nothing (this should also update ont he screen).
d.parameters()[1].value(20) // expecting parameter C to sum up to 30.
d.parameters()[2].value() // Still nothing.
So Ive tried sevral things but i think i'm barking up the wrong tree here.
Fetching the parent using ko.dataFor(document.body) or
fetching the object from the DOM using the same function.
I've played around with deferEvaluation as you can see in the code
to force KO to first create the parameters and then apply the
binding. seems to do nothing.
Tried creating a observableArray with the links to the params and a
computed based on the array but the problom remain.
Appreciate any help here.
Bonus question, without losing focus from the main one, somehing I cant explain going on on line 73.
Does anybody have a minute to take a look at a puzzling problem I'm having with Knockout JS and binding select lists?
The person's favourite color should be selected in the list by calling value: favColorId in the select list, rather than with the function-based call of value: favColorId(), something very strange is going on here, I've never used () in the past, it's also causing some other weird issues where it won't recall the value into the span (so changing the selected item does nothing).. I have tried recreating a simple sample as best I can demonstrating the issue.
http://jsfiddle.net/goneale/ph8Jw/
I have included my mapDictToArray() function but it simply converts a
javascript object into a key-value JS array. I wouldn't think that is
contributing to the problem.
Actually, that was part of the problem. The function returns a JavaScript array, not an observable array and therefor can't be used properly by Knockout. I've made the following changes to your code:
// The "mapDictToArray" makes a normal JS array, not a ko.observableArray();
// You can't simply "merge" a JS array with an observableArray(); you'll need
// some extra functionality for that: ko.utils.arrayPushAll()
// viewModel.colors(mapDictToArray(dict));
ko.utils.arrayPushAll(viewModel.colors(), mapDictToArray(dict));
// Apply the bindings *after* you've added the contents to the "colors" observable, in order to
// get the correct selected value
ko.applyBindings(viewModel);
That should do the trick (with the correct HTML without the () )!
JSFiddle.
UPDATE
I thought about my solution, but something wasn't correct. The only thing that was correct, was the part that you need to apply the bindings after you've added the contents of the colors observable. This is your fiddle, with that part moved down.
This works in your case, but you'll need to use the arrayPushAll method when there is already data inside the observableArray. This method merges, while you overwrite it when not using it (example with data inside the observable).
function eegetdropdownvalue_str(ctl){return ctl.selectedIndex>=0&&ctl[ctl.selectedIndex]?ctl[ctl.selectedIndex].value:''}
The above function is called with
co.p1A10=eegetdropdownvalue_str(document.formc.p1A10);
I want to switch the call over to jQuery to drop the document.form reference however doing this
co.p1A10=eegetdropdownvalue_str($('p1A10'));
Does not reference the control correctly - How should I do this?
There's two things wrong with your code.
First, $('p1A10') references nothing.
jQuery selectors work almost identically (if not completely identically) to the way css works.
So, just ask yourself how you would reference the object(s) in question in CSS and you're half way there.
I'm assuming that p1A10 is the name or id of an object. Since we're using CSS/jQuery syntax, this should be an id, although you can select by other attributes such as $("select[name='p1A10']") .
To reference an object by ID we use the # character (again, just like in CSS). So we can select your node via $('#p1A10').
The second problem is that your function is expecting a DOM object not a jQuery object. To keep your code intact, we need to say $('#p1A10')[0] where 0 is the first element within the collection of jQuery elements.
I've provided two examples to explain this a little better. One uses your existing infrastructure and one replaces it.
http://jsfiddle.net/TD6Uu/5/
Hope it helps.
Given a form with id formc and a select with name p1A10 you could e.g. use:
o.p1A10 = eegetdropdownvalue_str($('#formc select[name="p1A10"]').get(0));
If this doesn't do it, please provide use with the exact HTML structure