How do I clear an element before rendering? - lit-html

I have inherited an older project using jquery.
I am modernising the code.
In particular this $(selector).html("<h1>lol</h1>"); which as far as I understand is a full replacement of the selectors content.
I always end up with an error if I try to render to a cleared element.
This code:
const appDiv: HTMLElement = document.getElementById('app');
appDiv.innerHTML = `<h1>TypeScript Starter</h1>`;
// trying to replace jquery $(selector).html("<h1>lol</h1>");
appDiv.innerHTML = '';
render(html`<h1>lol</h1>`, appDiv);
appDiv.innerHTML = '';
render(html`<h1>lol</h1>`, appDiv);
Or see my stackblitz
I always get the following error:
Error in lit-html.js (93:55)
Cannot read properties of null (reading 'insertBefore')
Do you know what I am missing? 🧐
Thanks!
Note: This is a duplicate of my question (and based on a suggested technique) from a closed Lit Github Issue
Note: Maybe I am talking rubbish. I can't find a clear answer if render REPLACES content or APPENDS content. A concrete answer on that would be fine!

Lit v1 will clear the container before rendering the first time. Lit v2 will not.
Only clear the existing container content once before using render. After that render will correctly update content from previous render calls.
const appDiv: HTMLElement = document.getElementById('app');
appDiv.innerHTML = `<h1>TypeScript Starter</h1>`;
// trying to replace jquery $(selector).html("<h1>lol</h1>");
appDiv.innerHTML = '';
render(html`<h1>lol</h1>`, appDiv);
render(html`<h1>lol2</h1>`, appDiv);

Related

Flask-Admin GeoAlchemy2 example doesn't show a map

I'm trying to run this example about how to use Flask-Admin displaying maps: https://github.com/flask-admin/flask-admin/tree/master/examples/geo_alchemy.
In README.rst, there's this instruction:
You will notice that the maps are not rendered. To see them, you will have to register for a free account at Mapbox and set the MAPBOX_MAP_ID and MAPBOX_ACCESS_TOKEN config variables accordingly.
I already have a valid MAPBOX_ACCESS_TOKEN, and I went to MapBox to look for a MAPBOX_MAP_ID. There I read that MAP_ID was deprecated, and now I'll have to obtain a tileset ID, and it's described as a label composed by <my_mapbox_user_name>.the_tileset_ID itself.
So I located the code as they described in the instructions (in my case, mapbox-streets-v8) and fulfilled the config.py parameters:
MAPBOX_MAP_ID = '<my_mapbox_user_name>.mapbox-streets-v8'
MAPBOX_ACCESS_TOKEN = 'pk.eyJ1...'
However, I couldn't see any map displayed or any error message.
How can I fix it?
I think there is a small bug in file Lib\site-packages\flask_admin\static\admin\js\form.js. The original URL generated to get a tile is:
https://api.mapbox.com/styles/v1/mapbox/<MAPBOX_MAP_ID parameter>/tiles/12/2258/2457?access_token=<MAPBOX_ACCESS_TOKEN parameter>
However, the correct one is:
https://api.mapbox.com/styles/v1/<MAPBOX_MAP_ID parameter>/tiles/12/2258/2457?access_token=<MAPBOX_ACCESS_TOKEN parameter>
That is, I had to remove the mapbox word from the URL.
To do that I made some changes in form.js file:
//var mapboxUrl = 'https://api.mapbox.com/styles/v1/mapbox/'+window.MAPBOX_MAP_ID+'/tiles/{z}/{x}/{y}?access_token='+window.MAPBOX_ACCESS_TOKEN
var mapboxUrl = 'https://api.mapbox.com/styles/v1/'+window.MAPBOX_MAP_ID+'/tiles/{z}/{x}/{y}?access_token='+window.MAPBOX_ACCESS_TOKEN
Then, it's working now:

how to refresh jstree with html instead rebuilding it

my code builds an html and initiates the jstree with that html :
var html = buildHtmlunorderedList()
$("#tree").html(html);
$("#tree").jstree({
"core":{"multiple":false},
"state":{"key":"vmsTree22"},
"plugins":["state","sort"]
}).bind("select_node.jstree",handleLeftClick);`
This work perfect.
now , every few minutes the html is built again and i want to refresh the jstree with it without the need to destroy it and initiate again (which cause a flick every time the tree is built again) :
inside a loop {
html = buildHtmlunorderedList();
var tree = $('#tree').jstree({
"core":{"data":html}
});
tree.refresh(true);
}
but i am getting an error : Uncaught TypeError: Cannot read property 'className' of undefined
(in jstree.js : var c = this.get_container_ul()[0].className;)
which seams it doesn't find the first children of class jstree-children.
what i am doing wrong ?
I didn't find any straight forward example of how to refresh the entire html of the tree without destroying it and build it again.
thanks for any help
You can replace data as below. Check demo - Fiddle.
$("#tree").jstree().settings.core.data = newData;
$("#tree").jstree().refresh(true);

Protractor + ionicPopup

Has anyone succeeded in using Protractor to detect an ionicPopup alert?
I've tried all the workarounds suggested here but no luck.
I need Protractor to detect the alert and check the text in the alert.
Here's the class I wrote to test that the popup exists and to ensure the text is correct in the header and body:
var TestUtilities = function(){
this.popup = element(by.css('.popup-container.popup-showing.active'));
//Tests to see if $ionicPopup.alert exists
this.popupShouldExist = function() {
expect(this.popup.isDisplayed()).toBeTruthy();
};
//Tests to see if $ionicPopup.alert contains the text provided in the argument exists in the header
this.popupContainsHeaderText = function (text) {
this.popupShouldExist();
expect(this.popup.element(by.css('.popup-head')).getText()).toMatch(text);
};
//Tests to see if $ionicPopup.alert contains the text provided in the argument exists in the body
this.popupContainsText = function (text) {
this.popupShouldExist();
expect(this.popup.element(by.css('.popup-body')).getText()).toMatch(text);
};
};
module.exports=TestUtilities;
Also check out this site for more on testing Ionic in protractor it talks about how to check to see if the popup exists: http://gonehybrid.com/how-to-write-automated-tests-for-your-ionic-app-part-3/
I've tested Ionic popups successfully by setting the popup variable as follows:
var popup = element(by.css('.popup-container.popup-showing.active'));
And in the test:
expect(popup.isDisplayed()).toBeTruthy();
Ionic Popups are just made of DOM elements, so you should be able to use normal locators to find/test them. Because they're not made of alerts, the workarounds in the issue you linked to are probably not useful.
I got it - I saw a lot of issues out there trying to do it in very complex ways, but in the end I tried this and it turns out to be this simple.
Inspect your element and find its ng-repeat value, then
var button = element(by.repeater('button in buttons')).getText()
You also need to have the browser sit out somehow for a couple seconds so it doesn't resolve to the tests while the ionic popup isn't actually there.
For that, browser.sleep(3000);
That's it! However, getting the other button in there is proving to be a little problem. var button = element(by.repeater('button in buttons')).get(0) or .get(1) return undefined is not a function.
Please accept the answer if you like it! If I figure out how to get the other button, I'll post it here.

AngularJS - binding input file scope to a different scope

Wasn't sure how to properly title my question, I guess in my case it can also be titled "DOM manipulation not being detected by the scope", but it all depends on the approach of my problem.
To start off, I followed an official example on AngularJS main website with the Projects app which connects with Mongolab. The only difference is I want to add a file input, that reads file name and its lastModifiedDate properties and then applies those values to my form. To make file input work I followed this example here.
I made it work, but the problem is that when values get applied to my form scope is not picking up the changes.
I am doing DOM manipulation in my .apply() function and using $compile too, but something is missing. Or perhaps there's an easier way altogether without doing DOM manipulation?
Here's what I have so far, please take a look at this plunker - http://plnkr.co/edit/mkc4K4?p=preview
(Just click on the plus sign icon to add new entry, then try choosing a file.)
You need to add a watch statement in the CreateCtrl
function CreateCtrl($scope, $location, Movie) {
$scope.inputfile = {};
$scope.movie = {};
$scope.$watch('inputfile.file', function(value){
$scope.movie.filename = value ? value.name : '';
$scope.movie.dateadded = value ? value.lastModifiedDate : '';
})
$scope.save = function() {
Movie.save($scope.movie, function(movie) {
$location.path('/edit/' + movie._id.$oid);
});
};
}
Demo: Sample

Locating text within a div's ul/li

using .NET MVC/Razor, I am working on setting the validation summary manually client side using the following method for a few js client side operations which will not be handled in data annotations:
function RenderError(message) {
var myDiv = $('[data-valmsg-summary="true"]');
myDiv.removeClass("validation-summary-valid");
myDiv.addClass("validation-summary-errors");
var list = myDiv.find('ul');
$("<li />").html(message).appendTo(list);
}
This works fine, but obviously repeats the errors. What is the simplest way to check and see if the message has already been entered in a list item? Keeping in mind that I already have a handle to the div itself?
Thanks in advance
You could check in a if statement if the data-valmsg-summary field is true and skip it accordingly, does it make sense?