Is there a way to delay the ngx-bootstrap accordion opening? - ngx-bootstrap

<accordion [closeOthers]=true>
<accordion-group *ngFor="let activity of activities" [heading]="activity.Name" (click)="openPanel(activity)" (isOpenChange)="openStatusChange($event)">
<ul *ngFor="let chemical of chemicals">
<li>{{chemical.BrandName}}</li>
</ul>
<div *ngIf="!chemicals?.length > 0">No chemicals associated with this activity type.</div>
</accordion-group>
</accordion>
When the accordian header is clicked, it opens and runs and fires 'openPanel()' which is an http.get, which then populates the panel. If the array returns empty, the *ngIf will display the "no associated stuff" message.
The problem is there is a very slight lag between the time the accordion opens and the array is filled, so the chemicals array is always empty when the accordion opens. This makes it so the "no associated stuff" message appears for about half a second, then the list populates. So I am wondering if there is a way to either delay the opening until the array is populated, or suggestions welcome.

You could use a boolean flag or function for the ngIf. Set the flag when the http promise returns as successful, that way the ngIf only triggers after the http call promise is resolved.
something like:
http.get('url').subscribe(response => {
show = true;
});

Related

How to handle nested attributes in HTMX

I have a table like structure in my page and each row has data-hx-get attribute pointing to a url where django returns details for that row. But also in the same row I have an edit button where django returns the edit form for that item. I would like the entire row to be clickable and when clicked shows replaces itself with the details and also the edit button to replace the row with the form. It works fine for the users but when the edit button inside the row is clicked, in the console I get htmx:swapError as the row also receives the click event and does what it was supposed to do. The event on the button takes precedence and before the row it changes the content of the row and when the row gets the response, the data-hx-target for that is no more in the page. So, my question is, is there a way to tell htmx, when a nested element has data-hx-get, ignore the parent's hx directive.
<div
class="row item-row"
id="item-row-{{item.pk|unlocalize}}"
data-hx-get="{% url 'some url' item.pk %}
data-hx-swap="outerHTML"
data-hx-trigger="click"
data-hx-target="this">
...
<button
data-hx-get="{% url 'editurl' item.pk %}"
data-hx-swap="outerHTML"
data-hx-trigger="click"></button>
</div>
You can use the consume modifier for hx-trigger https://htmx.org/attributes/hx-trigger/. This will prevent the click event from bubbling up to the parent row.
<div
class="row item-row"
id="item-row-{{item.pk|unlocalize}}"
data-hx-get="{% url 'some url' item.pk %}"
data-hx-swap="outerHTML"
data-hx-trigger="click"
data-hx-target="this">
...
<button
data-hx-get="{% url 'editurl' item.pk %}"
data-hx-swap="outerHTML"
data-hx-trigger="click consume"></button>
</div>

How to disable blur call on the active element from SwiperJS in onTouchStart handler?

Is it possible to disable this blur call on the active element from SwiperJS in the onTouchStart event handler?
Some background:
For touch and desktop devices I'm using swiper for forms on swiper-slides. Within a form I'm using vue-select (a combobox).
The Problem: When the user selects an entry, the entry get not selected on the first time but on the second time.
<div class="swiper-container">
<div class="swiper-wrapper">
<div class="swiper-slide">
<div>First form</div>
<v-select :options="selectionEntries"></v-select>
</div>
<div class="swiper-slide">
<div>Second form</div>
<v-select :options="selectionEntries"></v-select>
</div>
</div>
</div>
See also this example on codepen
I figured out that it seems to work correctly:
When I remove the blur-listener on the input field of the vue-select box. But it is used to close the selection list when the user leaves the field.
When I comment out this blur call in SwiperJS. I'm not sure why it is used there.
The first point is not an option, so is it possible to disable the blur call of SwiperJS via configuration?
Currently I'm using this workaround (SwiperJS V6.4.1):
const swiper = new Swiper(".swiper-container", {
// Workaround part 1:
touchStartPreventDefault: false
})
// Workaround part 2:
swiper.touchEventsData.formElements = 'notExistingHtmlTagName'
Part 1: To handle mouse down and click events on all elements, set the swiper parameter touchStartPreventDefault: false.
That will disable this code block: https://github.com/nolimits4web/swiper/blob/9dead9ef4ba5d05adf266deb7e3703ceb199a241/src/components/core/events/onTouchStart.js#L90-L97
Part 2: Set swiper.touchEventsData.formElements = 'undefined' to define nothing as formElements. That will disable the code block that calls blur: https://github.com/nolimits4web/swiper/blob/9dead9ef4ba5d05adf266deb7e3703ceb199a241/src/components/core/events/onTouchStart.js#L81-L88

Accordion has a default active panel, but it won't open

I am using a frontend library called Element UI to create some accordions on my website. I got an array of objects that I like to create accordions for. FYI, from the element ui website: the v-model used on the accordion specifies the currently active panel. The name attribute is the unique identification of the panel. That means I can do:
<el-collapse v-model="activeName" accordion>
<el-collapse-item title="Consistency" name="1">
<div>content content content</div>
</el-collapse-item>
<el-collapse-item title="Consistency" name="2">
<div>more content more content more content</div>
</el-collapse-item>
</el-collapse>
One this loads, the first accordion will open since in the data object, activeName is set to 1:
data() {
return {
activeName: '1',
}
}
Now I thought I'd just loop through the array and create accordions for the items in my array, and binding the name attribute to the index + 1, so that the first item will have the name attribute equal to 1, the second to 2 etc. So:
<el-collapse v-model="activeName" accordion>
<el-collapse-item
v-for="(item, index) in experience"
:title="item.company"
:name="index + 1"
:key="index"
>
<div> content content content </div>
</el-collapse-item>
</el-collapse>
But for some reason, when the page loads, the first item in the accordion won't open automatically. They're all closed by default. I created a codesandbox with the problem that you can see for yourself here: codesandbox
The problem is that when you run a for loop and assign name, it's a number and not a string.
:name="index+1" <---- This is a number
But, activeName is a string. So, the values don't match and that's why the accordian does not open on page load.
Here's an updated sandbox: https://codesandbox.io/s/vue-template-ysm79
I changed activeName to a number. The for loop accordian will now open and the normal HTML accordians won't.

What is $emit(\'remove\') in vue js

I want to make some list item from array and want delete them when i click each list item.When i click each item each item get deleted but here $emit(\'remove\') is actually what in vue js plaese help.
<button v-on:click="$emit(\'remove\')">X</button>
seems it connected to emit event which is bind to that element.
<button v-on:click="$emit(\'remove\')">X</button>
is connected to this piece of code in the declaration, you can see this code is just above in your example
<li
is="todo-item"
v-for="(todo, index) in todos"
v-bind:title="todo"
v-on:remove="todos.splice(index, 1)"
></li>
here you can see:
v-on:remove="todos.splice(index, 1)"
this is the event so when you click on that button this will be fired and that item will be removed from the list.
and make sure this list items are component so it use that template to render each items.
if you have further question please feel free to ask.

safari - contenteditable, after making it empty, creates an element with text-align:center

In safari,
i had a simple edtable div with a input button, on deletion of the element (backspace or delete), caret moves to center of edtiable div with some inline styled p tag with text-align:center and inline style "color"
<div class="editable" contenteditable="true">
<input type="button" value="inputBtn" />
</div>
http://jsfiddle.net/VqCvt/
its a strange behavior observed only in safari.
Over a year after this post, this issue is still a problem. This issue is directly tied to the input tag. Once an input tag has been in a contenteditable element, Safari will attempt to make the style of the text similar to the input (I confirmed this by observing that the resulting style was different for type="text" vs type="button"). It's a very strange bug. I have found a workaround that works, but it's pretty absurd. My fix is basically to test when my main input no longer has content, and then removing the element, and re-adding it
<div id="content-wrapper">
<div contenteditable="true" id="content" role="textbox"></div>
</div>
and in my "keyup" listener, I put the following code
// Grab main editable content div
var element = document.getElementById("content");
// Check empty state conditions. These work for me, but you may have your own conditions.
if (element.getElementsByTagName("input").length == 0 &&
element.innerText.trim().length == 0) {
// Grab parent container
var elementContainer = document.getElementById("content-wrapper");
// Add a copy of your element to the same specifications. If you have custom style attributes that you set through javascript, don't forget to copy them over
elementContainer.innerHTML = '<div contenteditable="true" id="content" role="textbox"></div>';
// Re-focus the element so the user doesn't have to click again to keep typing
element = document.getElementById("content");
element.focus();
}
What this code does works for my case because input is the only elements which are allowed in my code other than text nodes and <br>, so I first check to make sure there are no input elements, and then make sure the innerText is empty (this indicates no content in my case, you may have to customize your conditions for the "empty" state). Once the empty state is confirmed, I replace the old div with a new one to the same specification, and the user never notices. A very strange issue with a hacky workaround, but I think contenteditables.
You could probably also strip out the HTML that Safari is generating, but for my case this solution is much simpler. I hope this helps someone in the future.