Vue.js ignored when a blade is included in another blade - javascript

I have created a product card view in Laravel. the card has a simple "accordion" ('Show Details') - closed by default - that is managed by Vue.js as well as a Vue.js quantity counter that changes the weight value in grams if you add products. It all functions very well on the card's view and it looks like this (closed):
I have another view in which I query my DB for product names with Vue.js to display all products of the same name as a result. The problem is when the cards are displayed on that "parent" view, they all appear with the accordion open and the counter is not responsive. It looks like so:
As you can see, the tailwindcss code is rendered without a problem but the Vue.js is being completely ignored (Although the parent view's Vue.js functions work perfectly) What am I doing wrong? What am I missing here? Why are the directives inside the included blade being ignored?
Here is the Vue.js method that manages the (product cards) views integration onto the parent (product name search) view:
setGearItem(gearItem) {
this.gearItem = gearItem;
this.modal = false;
console.log(gearItem);
document.getElementById("displaySearch").innerHTML = "";
axios.get('/send-name-get-ids/' + this.gearItem)
.then((response) => {
console.log(response.data);
if (response.data.length === 0) {
document.getElementById("displaySearch").innerHTML = `"<strong>${gearItem}</strong>" was not found in our database. You can add it manually:`;
this.generalForm = true;
return;
} else {
for (let i = 0; i < response.data.length; i++) {
axios.get('/gearitem/' + response.data[i])
.then((response) => {
console.log(response.data);
document.getElementById("displaySearch").innerHTML += response.data;
this.generalForm = false;
})
.catch((error) => {
document.getElementById("displaySearch").innerHTML =
"No items to display";
console.log(error);
});
}
}
});
},

The problem is in the .innerHTML method as Vue.js ignores anything added via this method even if it's an AJAX. The solution consists on changing the controller to return a JSON and not a blade view, then using the JSON to populate a Vue.js component to create the item's card. the setGearItem() method was changed like so:
setGearItem(gearItem) {
this.gearItem = gearItem;
this.modal = false;
console.log(gearItem);
document.getElementById("displaySearch").innerHTML = "";
this.displayItemCard = false;
axios.get('/send-name-get-ids/' + this.gearItem)
.then((response) => {
console.log(response.data);
this.gearItemId = response.data[0];
if (response.data.length === 0) {
document.getElementById("displaySearch").innerHTML =
`<p class="text-gray-700 ">
<strong class="capitalize">${gearItem}</strong>
was not found on our database. <br>You're free to add it manually! </p>`;
this.generalForm = true;
return;
} else {
this.displayItemCard = true;
}
});
},
the displayItemCard just activates the card component on the view and displays the correct card according to the id.

Related

How to accses to laravel if-else variable with jquery

I have a dating project. We are using laravel 6 and jquery 3.4.1
The problem is that I need to draw a div when receiving AJAX.
So, javascript and blade template :
static countNewMessages() {
$.get('/some/link/here', results => {
let total = 0;
if (results.length === 0) {
$('.chat__list-block').each(function (index) {
$(this).removeClass('chat__list-block_new');
});
$('.chat__list-non-read-counter').addClass('chat__list-non-read-counter_hidden').each(function (index) {
$(this).text('');
});
$('#number-of-new-messages').addClass('d-none').removeClass('d-flex').html('');
$('#inbox-messages-count-title').html('0');
return false;
}
results.forEach(v => {
if (Chat.containers?.threads) {
let threadElement = $('.chat__list-block[data-pid=' + v.from_userid + ']');
threadElement.addClass('chat__list-block_new');
threadElement.find('.chat__list-non-read-counter')
.addClass('chat__list-non-read-counter_hidden')
.text(v.count);
if (0 < threadElement.length && !threadElement.hasClass('chat__list-block_active') && 0 < v.count) {
threadElement.find('.chat__list-non-read-counter')
.removeClass('chat__list-non-read-counter_hidden');
}
}
total += v.count;
$('#number-of-new-messages').addClass('d-flex').removeClass('d-none').html(total);
$('#inbox-messages-count-title').html(total);
});
});
}
#if(count($threads))
<div>Chat requests</div>
#else
<div>No chat requests</div>
#endif
The standard if-else behavior in the template suits me fine. If a user visits the page but has no messages the second block is displayed, and if he has messages the first block is displayed. But if a user who is on the block "no chat requests" and receives new messages then the block "chat requests" is rendered only after a full refresh of the page.
If you need more information, please let me know
Try this :
#if(count($threads))
<div data-threads-count="{{ count($threads) }}">Chat requests</div>
#else
<div data-threads-count="{{ count($threads) }}">No chat requests</div>
#endif
Now you can access threads count by using data function in jquery ex :
$(selector).data('threads-count');
or
$(selector).attr('data-threads-count');
Both will return threads count
i hope it was useful 😊

getting more than one items from local storage using javscript

I am currently working on a project and struggling to implement Local Storages on my work.
About My Project:
I am trying to do a basic FILM LIST Project.
I have 3 inputs. I saved them but I am not able to get all items from storage when the "DOMContentLoaded" listener run.
I created a LocalStorage class and imported it to my app.js
I created a FILM class and imported it to my app.js
I created a UI class and imported it to my app.js
I am going to post my important functions and classes for you to check,
Film.js
class Film {
constructor(title, director, url) {
this.title = title;
this.director = director;
this.url = url;
}
}
export default Film;
UI.js
class UI {
constructor() {
}
static addFilmToUI(film) {
//console.log(film.title, film.director, film.url)
let html = ` <tr>
<td><img src="${film.url}" class="img-fluid img-thumbnail"></td>
<td>${film.title}</td>
<td>${film.director}</td>
<td>Delete Film</td>
</tr>`
document.getElementById("films").innerHTML += html;
} ...
LocalStorage.js
class LStorage {
constructor() {
}
static getAllItemsFromLocalStorage() {
let films;
if (localStorage.getItem("films") === null) {
films = [];
} else {
films = JSON.parse(localStorage.getItem("films"));
console.log(films)
}
return films;
}
static addItemsToLocalStorage(film) {
let films = this.getAllItemsFromLocalStorage();
films.push(film);
localStorage.setItem("films",JSON.stringify(films));
}}
App.js
const form = document.querySelector("form");
form.addEventListener("submit", createFilm);
document.addEventListener("DOMContentLoaded",function(){
let films = LS.getAllItemsFromLocalStorage();
Array.prototype.forEach.call(films,(element)=>{
UI.addFilmToUI(element)
})
})
function createFilm(e) {
e.preventDefault()
const title = document.getElementById("title");
const director = document.getElementById("director");
const url = document.getElementById("url");
let informations = [title.value, director.value, url.value];
if (informations.every((values) => values != "")) {
const createdFilm = new FILM(title.value, director.value, url.value);
UI.addFilmToUI(createdFilm);
LS.addItemsToLocalStorage([title.value,director.value,url.value]);
} else{
alert("Cant be empty!")
}
UI.clearInputs(title,director,url)
}
When I refresh my page the only thing I get is undefined.
When i upload only film the console output is:
[Array(3)]
0: (3) ["Avatar", "James Cameron", "js.png"]
length: 1
proto: Array(0)
Ah, I found my mistake. I send multiple params to a single-valued param function also when I calling my data from storage, I did kind of override I guess. I tried to invoke my data from where I put them into UI. That's why I confused. Therefore I created one function more which called loadAllData().
And also i adjust my eventListener function as well.
- LS.addItemsToLocalStorage(createdFilm)
document.addEventListener("DOMContentLoaded",function(){
let films = LS.getAllItemsFromLocalStorage();
UI.loadAllItems(films)
})
static loadAllItems(films){
const filmList = document.getElementById("films");
films.forEach((film)=>{
filmList.innerHTML += ` <tr>
<td><img src="${film.url}" class="img-fluid img-thumbnail"></td>
<td>${film.title}</td>
<td>${film.director}</td>
<td>Filmi Sil</td>
</tr>`
})
}

html button click to add value in javascript class

I have a few buttons with different categories. When the user clicks on the button, the correct category should be displayed. In every category, there are a few products, each with their own "add to cart"-button.
So, the user clicks "beds" and then adds item #3 to the cart (which updates and so on).
I have managed to do this with classes IF the user can't choose a category. It also works without classes if I add the buttons dynamically in js. But again, without allowing the user to choose a category.
I also want the user to be able to search for an item, get the item/ items displayed, and add it to the cart.
Get Products
class Products {
async getProducts() {
try {
const result = await fetch("/data/products.json");
const data = await result.json();
let products = data.items;
products = products.map((item) => {
const { category, title, price } = item;
const { id } = item.sys;
const image = item.image.url;
return { category, title, price, id, image };
});
return products;
} catch (error) {
console.log(error);
}
}
}
Display Products
class UI {
async displayProducts(products, searchText) {
let matches = products.filter(item => {
const regex = new RegExp(`^${searchText}`,'gi');
return item.category.match(regex);
})
let result = "";
matches.forEach((product) => {
result += `
<!-- single product -->
<article class="product">
<div class="img-container">
<img
src=${product.image}
alt="product"
class="product-img"
/>
<button class="bag-btn" data-id=${product.id}>
<i class="fas fa-shopping-cart">add to cart</i>
</button>
</div>
<h3>${product.title}</h3>
<h4>$${product.price}</h4>
</article>
<!-- end single product -->
`;
});
productDOM.innerHTML = result;
}
getBagButtons() {
const buttons = [...document.querySelectorAll(".bag-btn")];
In HTML I used onclick="displayProducts('bed')"
This will not work tho, since displayProducts is in a class.
I have also tried to add an id to each button and add an eventlistener in DOMContentLoaded, but that wrecks the rest of my DOMContentLoaded stuff
DOMContentLoaded
document.addEventListener("DOMContentLoaded", () => {
const ui = new UI();
const products = new Products();
// setup app
ui.setupAPP();
products
.getProducts()
.then((products) => {
ui.displayProducts(products);
Storage.saveProducts(products);
})
.then(() => {
ui.getBagButtons();
ui.cartLogic();
});
});
These are just a few of the things I've tried, but for each try, one issue is fixed but one or more issues are added, so I could really use some help here. Thanks!
These are the changes we made:
All category buttons gets this event listener
onclick="searchNdisplay(new UI, new Products, 'category text');"
This initializes the ui and products and they get displayed, so we changed it to use the searchNdisplay function
document.addEventListener("DOMContentLoaded", () => {
const ui = new UI();
const products = new Products();
// setup app
ui.setupAPP();
searchNdisplay(ui, products, "");
Storage.saveProducts(products);
});
This function repopulates the page with products that met the search criteria.
function searchNdisplay(ui, products, search)
{
products
.getProducts()
.then((products) => {
if (search == "")
{
ui.displayProducts(products);
}
else
{
ui.displayProducts(products, search);
}
})
.then(() => {
ui.getBagButtons();
ui.cartLogic();
});
}

How is it possible that piece of code that was working is now ignored?

I have coded a ajax based "JS TABS" containing .JSON file like 10 months ago, now wanted to reuse it, and can't find out why it's not working. I haven't touched it since and don't know where is the bug.
When i click the button to render products nothing prints out - except console telling me: items is undefined = so i moved it inside function changeCategoryItems(categoryId) { } well no errors but nothing renders...can someone help me ?
Here is a codepen reference of what i mean: https://codepen.io/Contemplator191/pen/WNwgypY
And this is JSON : https://api.jsonbin.io/b/5f634e0c302a837e95680846
If codepen is not suitable/allowed here is whole JS for that
let items = [];
const buttons = document.querySelectorAll('button');
const wrapper = document.querySelector('section.products');
buttons.forEach(function (button) {
button.addEventListener('click',event => {
changeCategoryItems(event.target.dataset.category);
});
});
function changeCategoryItems(categoryId) {
let items = [];
const buttons = document.querySelectorAll('button');
const wrapper = document.querySelector('section.products');
const viewItems = (categoryId == 0 ) ? items : items.filter(item => item.category == categoryId);
wrapper.innerHTML = "";
viewItems.forEach(item => {
const div = document.createElement('div');
div.setAttribute("class", "product");
div.innerHTML = createItem(item);
wrapper.appendChild(div);
});
};
function createItem(item) {
return `
<div class="product__img">
<img src="${item.img}" class="">
</div>
<div class="product__name _tc">
<h4 class="">${item.heading}</h4>
</div>
<div class="text-desc product__desc">
<p class="">${item.description}</p>
</div>
<div class="product__bottom-content">
<span class="product__info">${item.info}</span>
${item.btn}
</div>
`
}
fetch('https://api.jsonbin.io/b/5f634e0c302a837e95680846')
.then(function (res) { return res.json() })
.then(function (data) {
items = data.items;
changeCategoryItems(1);
});`
In your fetch you're trying to assign data.items to the items variable but the api doesn't return data with an items node so items is undefined. It's possible the api changed their return format since the last time you used it which would explain why it worked previously.
this seems to fix it
.then(function (data) {
items = data;
changeCategoryItems(1);
});
Your issue is in this line:
items = data.items;
Now, the returned value is an array, hence you can use it as it is.
The updated codepen

Cannot filter files using Kendo Upload with rRazor

I saw no information on this topic really, except for info on how to filter files when using the latest Kendo library. So I am posting how I did it for others to use if they need to.
This is Kendo being used in Razor Syntax:
#(Html.Kendo().Upload()
.Name("procfiles")
.Async(a => a
.Save("SavePF", "AccountEvent", new { id = Model.SeqNum })
.Remove("RemovePF", "AccountEvent", new { id = Model.SeqNum })
.AutoUpload(true)
).Files(f =>
{
if (Model != null && !string.IsNullOrEmpty(Model.ProcedureFile))
{
f.Add().Name(Path.GetFileName(Model.ProcedureFile));
}
})
.Multiple(false)
.ShowFileList(true)
.Events(e =>
{
e.Error("accountEventEditController.uploadProcFileError");
e.Select("accountEventEditController.onProcFileUploadSelect");
e.Upload("accountEventEditController.onProcFileUpload");
e.Success("accountEventEditController.onProcFileSuccess");
e.Remove("accountEventEditController.onProcFileRemove");
e.Complete("accountEventEditController.onProcFileComplete");
})
)
As you can see, you can hook into the "Select" event. Then I have a .js controller handler file, that executes the following code to filter file types.
var onChkFileUploadSelect = function (e, type) {
var files = e.files;
var acceptedFiles = [".pdf", ".xlsx"];
var isAcceptedImageFormat = ($.inArray(files[0].extension, acceptedFiles)) != -1;
console.log(files[0].extension);
if (!isAcceptedImageFormat) {
e.preventDefault();
$(targetErrorControl).fadeIn('slow').delay(3000).fadeOut('slow');
}
}
Hopefully this helps some out there.

Categories