How to open a div inside a single card on button click which is in loop - angular8

I have a card which has ngFor loop, so many cards can create and inside each card I have a button , on button click I am opening a div inside that card. But currently on buton click div is opening in every card as it is in loop. How to fix it

Maintain the proper id's for each div's inside the foreach loop so that it'll expand and collapse properly, for your reference below is the sample html and typescript code.
--.html
<div class="row" *ngFor="let item of itemList;let i=index;">
<div class="col">
<div class="row bg-light" (click)="onClick(item,i,item.collapsed)"
[attr.aria-expanded]="item.collapsed" aria-controls="item.name">
<div class="col background-grey">
<label>{{item.name}}</label>
</div>
</div>
<div id="{{item.name}}" [collapse]="item.collapsed" [isAnimated]="true" class="container">
// content goes here
</div>
</div>
--.ts
itemList = [];
ngOnInit() {
for(let i=0;i<5;i++){
const objItem = {name:'name'+i,collapsed:true};
this.itemList.push(objItem);
}
}
onClick(item,index,collapsed){
this.itemList[index].collapsed = !collapsed;
}

Related

v-on:click not working - dynamically added html element

I am trying to get all images for a category using Vue
<div class="col-md-12 col-sm-2 p-2">
<a v-on:click="onCategoryManageImageClick($event)" data-target="#location-
category-images">
</span>
</a>
</div>
So the event onCategoryManageImageClick ($event) does not work, if I am adding a html block and then click on get image button.
this is index.js
methods:{
onImagesTabClick(){
this.$root.$emit('activated-tab:location-images');
},
onCategoriesTabClick(){
window.j1App.eventBus.$emit("j1-location-image-list:shown");
},
onCategoryManageImageClick: function(event) {console.log('working event..');
event.preventDefault();
window.j1App.eventBus.$emit("j1-location-category-image-
list:shown",event.currentTarget.id);
}
}
So basically it need to to work like we do in jQuery
$(document).on('click',function{
})
So it works either page load or if adding any new html element on DOM. same I want in Vue.
You cannot alter the Vue template outside of Vue. That won't work. Vue compiles the template once when starting up and adds the event listeners to the rendered elements. If you add elements afterwards, Vue will not know about them.
The correct way of doing this would be to add those new elements in Vue.
<div
class="col-md-12 col-sm-2 p-2"
v-for="item in items"
:key="item.id"
>
<a
v-on:click="onCategoryManageImageClick($event, item)"
data-target="#location-category-images"
>
</a>
</div>
See https://v2.vuejs.org/v2/guide/list.html for documentation. In this case you need the items array variable in data and add more array elements to it, if you need more links.
Try raplacing your a tag with p
<div class="col-md-12 col-sm-2 p-2">
<p v-on:click="onCategoryManageImageClick" data-target="#location-
category-images">
</p>
</div>

Materialize modal is not working in Angular

ts file
html file
This is the code in my project. When clicking on modal button it's not showing anything.
HTML:
<button data-target="modal1" class="btn modal-trigger">Modal</button>
<!-- Modal Structure -->
<div id="modal1" class="modal">
<div class="modal-content">
<h4>Modal Header</h4>
<p>A bunch of text</p>
</div>
<div class="modal-footer">
Agree
</div>
</div>
JavaScript:
declear const M;
document.addEventListener('DOMContentLoaded', function() {
var elems = document.querySelectorAll('.modal');
var instances = M.Modal.init(elems);
});
have you imported the css,js correctly? can you give us more details about your code? e.g How does your .html looks like and how is your folder structure etc?

Using vuejs with existing html

I have a list of elements, rendered server-side.
Each item has a button that changes its status.
<div class="list">
<div class="list-item" data-is-published="1" data-item-id="11">
<div class="item-link">Item 1</div>
<form method="post" class="list-item-form">
<div class="vue-mount">
<input type="submit" name="changeStatus" class="button-unpublish" value="Unpublish">
<!-- some hidden fields -->
</div>
</form>
</div>
<div class="list-item" data-is-published="1" data-item-id="12">
<div class="item-link">Item 2</div>
<form method="post" class="list-item-form">
<div class="vue-mount">
<input type="submit" name="changeStatus" class="button-unpublish" value="Unpublish">
<!-- some hidden fields -->
</div>
</form>
</div>
</div>
I'm using the following code to replace each item with a vue component
var ms = document.querySelectorAll('.vue-mount')
for (var i = 0; i < ms.length; i++) {
new Vue({
render: h => h(SubscriptionButton)
}).$mount(ms[i])
}
And on the component i get the values of data-is-published and data-item-id and set them on the component
<template>
<input
type="submit"
#click.prevent="changeStatus()"
:value="isPublished === 1 ? 'Unpublish' : 'Publish'">
</template>
<script>
export default {
....
created: function () {
const el = this.$root.$el.parentNode.parentNode
const status = el.dataset.isPublished
this.isPublished = parseInt(status)
this.itemID = el.dataset.itemID
}
}
I'm doing it this way to ensure that it works even if javascript is disabled, but the part this.$root.$el.parentNode.parentNode doesn't feel right.
Is the way I'm doing it ok? Are there better ways to achieve the same?
EDIT
I can put the data attributes on the element that vue will mount to and access them with this.$root.$el.dataset.
What I'm not sure about is how compliant to the best practices the use of this.$root.$el is.
You could use Element.closest (with a polyfill if IE support is required)
const el = this.$root.$el.closest("*[data-is-published]");
That avoids having to know the hierarchy depth of the DOM.
Info on MDN
Edited to add:
The appropriateness of using this.$root.$el depends on how you plan to structure the code. If the element you're trying to find is guaranteed to be a parent of the Vue application, then starting the search from $root is fine. If that bothers you, though, starting the search from this.$el instead would work.
The less conventional part of your approach is that it effectively creates a separate Vue application for each .vue-mount

How to show component selector on click event Angular5

I am getting issue while display another component on click event, here is my code:
<div (click)="showThis = true"></div>
<div class="" [ngClass]="{'hide': showThis}"></div>
<div class="" [ngClass]="{'show': showThis}">
<another-screen></another-screen>
</div>
its displaying both, first should display without any click, if click event then this hide first and another component will display
means hide and show class will apply
any help
Thanks
Why you don't use hidden:
<div (click)="showThis = true"></div>
<div class="" [hidden]="!showThis"></div>
<div class="" [hidden]="showThis">
<another-screen></another-screen>
</div>
*ngIf removes the html element from DOM but [hidden] is use for display none or block html element same as hide and show
Why not use *ngIf
<div (click)="showThis = true"></div>
<div *ngIf="!showThis "></div>
<div *ngIf="showThis ">
<another-screen></another-screen>
</div>

how to fix jquery error "Uncaught TypeError: Cannot read property 'style' of undefined" for blue-imp gallery in modal Bootstrap?

I used bootstrap 3 and blueimp-gallery in a web html5. My problem is a carousel-gallery dont show images and receive a error in a console "Uncaught TypeError: Cannot read property 'style' of undefined" when i use a blueimp-gallery-carousel in a modal div, but if i enter in a developer tools for chrome, this error disappears, and the images show in carousel-gallery.
The code.
<!-- Portfolio Modals -->
<!-- Use the modals below to showcase details about your portfolio projects! -->
<!-- Portfolio Modal 1 -->
<div class="portfolio-modal modal fade" id="portfolioModal1" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-content">
<div class="close-modal" data-dismiss="modal">
<div class="lr">
<div class="rl">
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-lg-8 col-lg-offset-2">
<div class="modal-body">
<h2>Vinilos</h2>
<div id="links">
1
2
3
</div>
<div id="blueimp-gallery-carousel" class="blueimp-gallery blueimp-gallery-carousel blueimp-gallery-controls">
<div class="slides"></div>
<h3 class="title"></h3>
<a class="prev">‹</a>
<a class="next">›</a>
<a class="play-pause"></a>
<ol class="indicator"></ol>
</div>
<p>Vinilos para rotulacion, decorativos, efecto espejo, fibra de carbono, refractivos, hologramas y farolas</p>
<button type="button" class="btn btn-primary" data-dismiss="modal"><i class="fa fa-times"></i> Cerrar Producto</button>
</div>
</div>
</div>
</div>
</div>
</div>
and my javascript
<script>
document.getElementById('links').onclick = function (event) {
event = event || window.event;
var target = event.target || event.srcElement,
link = target.src ? target.parentNode : target,
options = {index: link, event: event},
links = this.getElementsByTagName('a');
blueimp.Gallery(links, options);
};
</script>
<script>
blueimp.Gallery(
document.getElementById('links').getElementsByTagName('a'),
{
container: '#blueimp-gallery-carousel',
carousel: true,
}
);
</script>
and the link web problem
http://www.colombiawaterprint.com/web/index3.html
How i Solve this error?
I believe your problem is that your blueimp gallery is initially hidden as it is in a Bootstrap Modal. As such, when you first initialize the gallery it can't find the gallery. I think all you need to do is wait for the Bootstrap modal to be shown and then initialize the gallery.
Bootstrap triggers an event that you can listen for for this very purpose - http://getbootstrap.com/javascript/#modals-events - You probably want the shown.bs.modal event.
You would use it something like this. (assuming jQuery is loaded)
$('#portfolioModal1').on('shown.bs.modal', function (e) {
blueimp.Gallery(
document.getElementById('links').getElementsByTagName('a'),
{
container: '#blueimp-gallery-carousel',
carousel: true,
}
);
})
Bear in mind this is untested code and may not 'just work'. But hopefully you get the idea. You also may want to do a test to see if you've already initialized the gallery, as it stands this would re-initialize it every time the shown.bs.modal event was fired.