Polymer injectBoundHTML() not working properly - javascript

element that shows events. The events come from a JSON file and are loaded by core-ajax
It has a detail and a non-detail template, which can be toggled.
At first the non Detail template is loaded, then you can toggle additional information and the seccond template is loaded.
<template if="{{showDetail}}" >
<core-ajax auto
response="{{data}}"
on-core-response="{{ajaxHandler}}"
url ="http://localhost:8080/myevents/getDetailEvent={{nummer}}";
handleAs="json"></core-ajax>
<div class="showbox" >
<h2 id= "title"> </h2>
<p><b>Start:</b> {{data.startDate }}</p>
<p><b>Ende:</b> {{data.endDate }}</p>
<p id = "place"></p> </br>
<p id = "description"></p> </br>
<p id = "manager"></p> </br>
<button on-tap="{{toggleView}}">Less</button>
</div>
</template>
Non-Detail Template
<template if="{{!showDetail}}" >
<core-ajax auto
response="{{data}}"
on-core-response="{{ajaxHandler}}"
url ="http://localhost:8080/myevents/getEvent={{number}}";
handleAs="json"></core-ajax>
<div class="showbox" >
<h2 id= "title"> </h2>
<p><b>Start:</b> {{data.startDate}}</p>
<p id = "description"></p> </br>
<button on-tap="{{toggleView}}">More</button>
</div>
</template>
In my JSON I have a lot of HTML Tags thats why I use injectBoundHTML() to output them on my Screen. Here is my dataChanged method, which gets called when the component is loaded the first time, or I click the toggle Button:
dataChanged : function() {
if (this.data){
if(this.showDetail) {
this.injectBoundHTML(this.data.titleDe, this.$.titleDe);
this.injectBoundHTML(this.data.description, this.$.description);
this.injectBoundHTML(this.data.manager, this.$.manager);
} else {
this.injectBoundHTML(this.data.titleDe, this.$.titleDe);
this.injectBoundHTML(this.data.description, this.$.description);
}
}
}
When the component is loaded the first time, injectBoundHTML() is working and injects all of the content coming from the json. When I push the toggle Button no injection takes place! If I add the JSON content in the dataChanged MEthod without injection, it works!
What am I doing wrong?

Related

How can I use jquery to append a div for me which also includes all of it's nested divs as well?

When a user creates a product, I want that product to be broadcasted to all other users and dynamically added to their screens. So far the broadcast aspect works amazingly.
But how can I dynamically add in this '.product' class, as well as all of a nested divs in an easy way? At the moment the only thing I can think of is copying and pasting all of it's divs in a jquery variable and adding it that way- there must be an easier way.
Here is where products are first loaded in when the page loads
<div class="product" id="{{$product->id}}">
<div class="product-image"><img src="/imgs/products/{{$product->type_id}}.png"></div>
<div class="product-content">
<div class="product-title" id="product-title">
{{ strtoupper(\App\ProductType::where('id', $product->type_id)->first()->name)}}
</div>
<div class="product-price">PRICE PER UNIT: <div class="price-value" id="price">{{$product->price}}</div> EXENS</div>
<br/>
QUANTITY: <div class="quantity-value" id="quantity">{{$product->quantity_available}}</div>
#if(strpos(\App\Group::where('id', $player->group_id)->first()->options, "\"showName\":true") !== false)
<br/>
SELLER: <div class="seller" id="seller">{{\App\User::where('id',$product->seller_id)->first()->name}}</div>
#endif
<br/>
PRICE: <div class="total-price" id="total-price">{{$product->price * $product->quantity_available}}</div>
<form class="buy-product-form" action="/UoE/buy-product/{{$product->id}}" method="POST">
{{csrf_field()}}
<button class="pull-right btn btn-primary">BUY NOW</button>
</form>
</div>
</div>
When the event is received the only way I can think of doing it as:
var productToAdd="<div class='buy-product-form'><div id='price'></div> " +
"" +
"" + //insert a massive string here containing all the other aforementioned sub-divs
"" + //And populate with json data
"" +
"</div>";
$('.content').append(productToAdd);
My solution was to take the entire code posted in the question and do make it as a one big HTML tag. That way my JS function can append the page with a HTML product div and it will already be bound with the necessary event listeners.

VueJs: How to reuse bootstrap modal dialog

I've created three simple buttons that will trigger three different bootstrap modal dialog. The modal dialogs are "Add Product", "Edit Product" and "Delete Product". Both the Add and Edit modal dialogs contain a form with two input elements, whereas the Delete modal dialog contains a simple text. I realise that my code becomes very messy and hard to maintain. Hence, I have the following question:
1) How do I reuse the modal dialog, instead of creating 3 separate dialogs?
2) How do I know which modal dialog has been triggered?
Update: I've developed a soultion where I will include conditional statements such as v-if, v-else-if and v-else to keep track of which button the user click. However, I still feel that there is a better solution to this. Can anyone help/advice me?
Below is my current code:
<template>
<div>
<b-button v-b-modal.product class="px-4" variant="primary" #click="addCalled()">Add</b-button>
<b-button v-b-modal.product class="px-4" variant="primary" #click="editCalled()">Edit</b-button>
<b-button v-b-modal.product class="px-4" variant="primary" #click="deleteCalled()">Delete</b-button>
<!-- Modal Dialog for Add Product -->
<b-modal id="product" title="Add Product">
<div v-if="addDialog">
<form #submit.stop.prevent="submitAdd">
<b-form-group id="nameValue" label-cols-sm="3" label="Name" label-for="input-horizontal">
<b-form-input id="nameValue"></b-form-input>
</b-form-group>
</form>
<b-form-group id="quantity" label-cols-sm="3" label="Quantity" label-for="input-horizontal">
<b-form-input id="quantity"></b-form-input>
</b-form-group>
</div>
<div v-else-if="editDialog">
<form #submit.stop.prevent="submitEdit">
<b-form-group id="nameValue" label-cols-sm="3" label="Name" label-for="input-horizontal">
<b-form-input id="nameValue" :value="productName"></b-form-input>
</b-form-group>
</form>
<b-form-group id="quantity" label-cols-sm="3" label="Quantity" label-for="input-horizontal">
<b-form-input id="quantity" :value="productQuantity">5</b-form-input>
</b-form-group>
</div>
<div v-else>
<p class="my-4">Are You Sure you want to delete product?</p>
</div>
</b-modal>
</div>
</template>
<script>
export default {
data() {
return {
productName: "T-Shirt",
productQuantity: 10,
addDialog: false,
editDialog: false,
deleteDialog: false
};
},
methods: {
addCalled() {
this.addDialog = true;
},
editCalled() {
this.editDialog = true;
this.addDialog = false;
this.deleteDialog = false;
},
deleteCalled() {
this.deleteDialog = true;
this.addDialog = false;
this.editDialog = false;
}
}
};
</script>
<style>
</style>
As already mentionned, I would have use slots and dynamic component rendering to accomplish what you're trying to do in a cleaner way.
See snippet below (I didn't make them modals as such but the idea is the same).
This way, you can have a generic modal component that deals with the shared logic or styles and as many modalContentsub-components as needed that are injected via the dedicated slot.
Vue.component('modal', {
template: `
<div>
<h1>Shared elements between modals go here</h1>
<slot name="content"/>
</div>
`
});
Vue.component('modalA', {
template: `
<div>
<h1>I am modal A</h1>
</div>
`
});
Vue.component('modalB', {
template: `
<div>
<h1>I am modal B</h1>
</div>
`
});
Vue.component('modalC', {
template: `
<div>
<h1>I am modal C</h1>
</div>
`
});
new Vue({
el: "#app",
data: {
modals: ['modalA', 'modalB', 'modalC'],
activeModal: null,
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<button v-for="modal in modals" #click="activeModal = modal"> Open {{ modal }} </button>
<modal>
<template slot="content">
<component :is="activeModal"></component>
</template>
</modal>
</div>
Update
Now, You might think how will you close your modal and let the parent component know about it.
On click of button trigger closeModal for that
Create a method - closeModal and inside commonModal component and emit an event.
closeModal() {
this.$emit('close-modal')
}
Now this will emit a custom event which can be listen by the consuming component.
So in you parent component just use this custom event like following and close your modal
<main class="foo">
<commonModal v-show="isVisible" :data="data" #close- modal="isVisible = false"/>
<!-- Your further code -->
</main>
So as per your question
A - How do I reuse the modal dialog, instead of creating 3 separate dialogs
Make a separate modal component, let say - commonModal.vue.
Now in your commonModal.vue, accept single prop, let say data: {}.
Now in the html section of commonModal
<div class="modal">
<!-- Use your received data here which get received from parent -->
<your modal code />
</div>
Now import the commonModal to the consuming/parent component. Create data property in the parent component, let say - isVisible: false and a computed property for the data you want to show in modal let say modalContent.
Now use it like this
<main class="foo">
<commonModal v-show="isVisible" :data="data" />
<!-- Your further code -->
</main>
The above will help you re-use modal and you just need to send the data from parent component.
Now second question will also get solved here How do I know which modal dialog has been triggered?
Just verify isVisible property to check if modal is open or not. If isVisible = false then your modal is not visible and vice-versa

Copy HTML from element, replace text with jQuery, then append to element

I am trying to create portlets on my website which are generated when a user inputs a number and clicks a button.
I have the HTML in a script tag (that way it's invisible). I am able to clone the HTML contents of the script tag and append it to the necessary element without issue. My problem is, I cannot seem to modify the text inside the template before appending it.
This is a super simplified version of what I'd like to do. I'm just trying to get parts of it working properly before building it up more.
Here is the script tag with the template:
var p = $("#tpl_dashboard_portlet").html();
var h = document.createElement('div');
$(h).html(p);
$(h).find('div.m-portlet').data('s', s);
$(h).find('[data-key="number"]').val(s);
$(h).find('[data-key="name"]').val("TEST");
console.log(h);
console.log($(h).html());
console.log(s);
$("div.m-content").append($(h).html());
<script id="tpl_dashboard_portlet" type="text/html">
<!--begin::Portlet-->
<div class="m-portlet">
<div class="m-portlet__head">
<div class="m-portlet__head-caption">
<div class="m-portlet__head-title">
<h3 class="m-portlet__head-text">
<span data-key="number"></span> [<span data-key="name"></span>]
</h3>
</div>
</div>
<div class="m-portlet__head-tools">
<ul class="m-portlet_nav">
<li class="m-portlet__nav-item">
<i class="la la-close"></i>
</li>
</ul>
</div>
</div>
<!--begin::Form-->
<div class="m-portlet__body">
Found! <span data-key="number"></span> [<span data-key="name"></span>]
</div>
</div>
<!--end::Portlet-->
</script>
I'm not sure what I'm doing wrong here. I've tried using .each as well with no luck. Both leave the value of the span tags empty.
(I've removed some of the script, but the variable s does have a value on it)
You have two issues here. Firstly, every time you call $(h) you're creating a new jQuery object from the original template HTML. As such any and all previous changes you made are lost. You need to create the jQuery object from the template HTML once, then make all changes to that object.
Secondly, the span elements you select by data-key attribute do not have value properties to change, you instead need to set their text(). Try this:
var s = 'foo';
var p = $("#tpl_dashboard_portlet").html();
var $h = $('<div />');
$h.html(p);
$h.find('div.m-portlet').data('s', s);
$h.find('[data-key="number"]').text(s);
$h.find('[data-key="name"]').text("TEST");
$("div.m-content").append($h.html());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script id="tpl_dashboard_portlet" type="text/html">
<div class="m-portlet">
<div class="m-portlet__head">
<div class="m-portlet__head-caption">
<div class="m-portlet__head-title">
<h3 class="m-portlet__head-text">
<span data-key="number"></span> [<span data-key="name"></span>]
</h3>
</div>
</div>
<div class="m-portlet__head-tools">
<ul class="m-portlet_nav">
<li class="m-portlet__nav-item">
<i class="la la-close"></i>
</li>
</ul>
</div>
</div>
<div class="m-portlet__body">
Found! <span data-key="number"></span> [<span data-key="name"></span>]
</div>
</div>
</script>
<div class="m-content"></div>
In my case only this is working:
var template = $('template').clone(true, true); // Copies all data and events
var $h = $('<div />');
$h.html(template);
$h.find('.input-name').attr('value', "your value here"); // Note: .val("your value here") is not working
$('.list').prepend($h.html());

HTML Form: Make div as submit button

I've created a webpage including a folder structure hierarchy using –html/php/js/mysql.
Therefore, I've created a design. It's simply a parent div with the class of folders and inside all folders are listed with an <h2> as the name. Through PHP I've set the folder ID as a custom attribute on each folder div:
<div class="folders">
<div data-id="12452">
<h2>Folder 1</h2>
</div
<div data-id="12453">
<h2>Folder 2</h2>
</div
<div data-id="12454">
<h2>Folder 3</h2>
</div
</div>
Now, I would like to do that when someone clicks on folder one, a get parameter should be set in the url.
So basically the URL:
mywebpage.com/index.php ->'clicks folder' -> mywebpage.com/index.php?folder=12452
I have a couple of ideas how I could achieve that, like creating a hidden form that will be submitted with javascript when clicking a folder div, but I'm not quite sure which way is the best and cleanest.
I appreciate all the help.
You could do something like this, adding a click handler on the parent, and track which child were clicked on, and get its data-id
From there you can e.g. assign that url to a form and post it using the form's submit() method
Stack snippet
document.querySelector('.folders').addEventListener('click', function(e) {
if (e.target.closest('div').dataset.id) {
var url = "mywebpage.com/index.php?folder=" + e.target.closest('div').dataset.id;
console.log(url);
// e.g.
/*
var form = document.querySelector('form');
form.action = url;
form.hidden_field.value = "some value";
form.submit();
*/
}
})
<div class="folders">
<div data-id="12452">
<h2>Folder 1</h2>
</div>
<div data-id="12453">
<h2>Folder 2</h2>
</div>
<div data-id="12454">
<h2>Folder 3</h2>
</div>
</div>
<form id="the_form">
<input type="hidden" name="hidden_field" value="">
</form>
Since you're using jQuery you could attach a simple click like the following snippet shows.
NOTE: If you want from the h2 to looks like a clickable element you count change the cursor to pointer in your CSS rules like :
.folders h2 {
cursor: pointer;
}
$('.folders h2').click(function() {
var folder_id = $(this).parent().data('id');
//This line was added just for log purpose
console.log('?folder=' + folder_id);
//Uncomment the following line that will redirect you with folder "id" as parameter
//location.href = '?folder=' + folder_id;
})
.folders h2 {
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="folders">
<div data-id="12452">
<h2>Folder 1</h2>
</div>
<div data-id="12453">
<h2>Folder 2</h2>
</div>
<div data-id="12454">
<h2>Folder 3</h2>
</div>
</div>

Polymer Load Product Page data from JSON

Working with an e-commerce store application with polymer
I'm loading products array using polymer core-ajax and using core-animated pages to display product thumbnail and product detail page (full view) but I only wanted to load the product details when clicking on each product thumb, How can I do this
Find the HTML
<div id="article-content" >
<template is="auto-binding" id="page-template" >
<core-ajax
id="ajaxpolo" auto
url="./json/products.json"
handleAs="json"
on-core-response="{{handleResponse}}" response="{{headerList}}" on-core-response="{{postsLoaded}}">
</core-ajax>
<core-animated-pages id="fpages" flex selected="{{$.polo_cards.selected}}" on-core-animated-pages-transition-end="{{transitionend}}" transitions="cross-fade-all slide-from-right">
<section vertical layout>
<div id="noscroll" fit hero-p>
<div id="container" flex horizontal wrap around-justified layout cross-fade >
<section on-tap="{{selectView}}" id="polo_cards" >
<template repeat="{{item in headerList}}">
<div class="card" vertical center center-justified layout hero-id="item-{{item.id}}" hero?="{{$.polo_cards.selected === item.id || lastSelected === item.id }}" > <span cross-fade hero-transition style="">{{item.name}}</span></div>
</template>
</section>
</div>
</div>
</section>
<template repeat="{{item in headerList}}">
<section vertical layout>
<div class="view" flex vertical center center-justified layout hero-id="item-{{item.id}}" hero?="{{$.polo_cards.selected === item.id || $.polo_cards.selected === 0}}" >
<core-icon-button class="go_back" icon="{{$.polo_cards.selected != 0 ? 'arrow-back' : 'menu'}}" on-tap="{{goback}}"></core-icon-button>
{{item.name}} <span cross-fade class="view-cont" style="height:1000px; overflow:scroll;"></span></div>
</section>
</template>
</core-animated-pages>
</template>
first you would set the auto attribute of core ajax to false. auto="false" that would stop core-ajax from grabbing data by it's self. then set up a on-tap or on-click attribute on the element you want to be the click / tap handler. on-tap="{{getThem}}" then create the function.
getThem: function () {
this.$.ajaxpolo.go();
}
that should get it. hope it helps.
edit: you will want to grab a few more things with your event.
on the click / tap handler add the id of the item you wish to get to a generic attribute. (stay away from normal attributes. ie id, title and so forth) dataId I will call it.
<div on-tap="{{getThem}}" dataId="{{product_id}}"></div>
then in your function you get a few more things with the event as i said before.
getThem: function (event, detail, sender) {
var id = sender.attributes.dataId.value;
// do something with id
}
i just realized i may have misunderstood when you were talking about php. sorry.

Categories