Clearing browser cache with aurelia bundle revision - aurelia

I'm getting a 404 on my app-build.js bundle whenever I publish (AWS). The browser is referencing the previous bundle revision (e.g., dist/app-build-cf4...).
Even with a new bundle revision number and using "System.cacheBust" on the app-build file, it's still holding on to the old rev #.
I have to manually clear the cache to get the site to load.
Index.cshtml
...
<body aurelia-app="main" class="page">
<div>
<div class="splash text-darker-clr" >
<div class="message">
<span>Site</span>
<br />
<div id="ajax-loading-screen" data-disable-fade-on-click="0" data-effect="standard" data-method="standard">
<div class="loading-icon">
<span class="fa fa-circle-o-notch fa-spin spin"></span>
</div>
</div>
</div>
</div>
<script src="jspm_packages/system.js"></script>
<script src="config.js"></script>
<script>
var systemLocate = System.locate; System.cacheBust = "?bust=" + Date.now(), System.locate = function (a) { var b = this; return Promise.resolve(systemLocate.call(this, a)).then(function (a) { return a.lastIndexOf("html.js") > -1 ? a : a.lastIndexOf("css.js") > -1 ? a : a + b.cacheBust }) };
System.import('aurelia-bootstrapper');
</script>
</div>
</body>
bundles.js
module.exports = {
"bundles": {
"dist/app-build": {
"includes": [
"[**/*.js]",
"**/*.html!text",
"**/*.css!text"
],
"options": {
"inject": true,
"minify": true,
"depCache": true,
"rev": false
}
},
"dist/aurelia": {
"includes": [
"aurelia-framework",
"aurelia-bootstrapper",
"aurelia-fetch-client",
"aurelia-router",
"aurelia-animator-css",
"aurelia-templating-binding",
"aurelia-polyfills",
"aurelia-templating-resources",
"aurelia-templating-router",
"aurelia-loader-default",
"aurelia-history-browser",
"aurelia-logging-console",
"bootstrap",
"bootstrap/css/bootstrap.css!text",
"fetch",
"jquery",
"moment",
"aurelia-bootstrap-datepicker",
"aurelia-authentication",
"aurelia-api",
"aurelia-dialog"
],
"options": {
"inject": true,
"minify": true,
"depCache": false,
"rev": false
}
}
}
};

Related

How to make a list containing checkboxes attached to object in a v-for directive switch state safely (W/O switching other checkboxes in the list)?

I'm trying to make a client-side-only todolist that uses VueJS (2.x). Here is my HTML:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>To-do List</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">
</head>
<body>
<div id="app">
<h1>To-do List</h1>
<h2>Completed Tasks!</h2>
<ul>
<li v-for="item in complete">{{ item.description }}<input type="checkbox" :checked="item.done" #change="item.done = false"></li>
</ul>
<h2>Uncompleted Tasks!</h2>
<ul>
<li v-for="item in uncomplete">{{ item.description }}<input type="checkbox" :checked="item.done" #change="item.done = true"></li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue#2.7.13/dist/vue.js"></script>
<script type="module" src="scripts/app.js"></script>
</body>
</html>
Then in scripts/app.js I did this:
'use strict'
let app = new Vue({
el : "#app",
data : {
tasks: [
{ description: 'Say Hello', done: true },
{ description: 'Review Code', done: false },
{ description: 'Read Emails', done: false },
{ description: 'Reply to Emails', done: false },
{ description: 'Wash The Dishes', done: true },
{ description: 'Stop Working', done: true },
]
},
computed : {
complete : function() {
return this.tasks.filter(task => task.done === true);
},
uncomplete : function() {
return this.tasks.filter(task => task.done === false);
}
}
});
My issue is simple: when I change the state of a checkbox (checking it or unchecking it) in a given list, the checkbox that directly follows it switches state as well.
I can't figure out why this happens and how to fix it. If one can tell me why this happens (so that I don't have to come back here whenever I have a misbehaving v-for/switch-state) as well as how to fix it, that would be great!
first of all. You'd better use Function in data instead of Object, or it may cause an update error.
Since Function is accepted only when used in a component definition.
// wrong
data: {
tasks: []
}
// correct
data() {
return {
task: []
}
}
You may not change the computed attribute directly which only has a Computed Getter in default. If you want to handle the computed attribute, give a Computed Setter to it.
// wrong
computed: {
complete(){
return this.tasks.filter(task => task.done === true);
},
}
// right
computed: {
complete: {
get() {
return this.tasks.filter(task => task.done === true);
},
set(value) {
this.task.forEach((task, index) => {
let matched = value.find(({ description }) => description === task.description);
if(matched) {
this.task[index] = matched;
}
});
}
}
}
you can't bind the value via v-for, because vue2 can't recognize the changes in the array.
<!-- wrong -->
<li
v-for="item in complete">
{{ item.description }}
<input
type="checkbox"
:checked="item.done"
#change="item.done = false">
</li>
<!-- correct -->
<li
v-for="(item, index) in complete">
{{ item.description }}
<input
type="checkbox"
:checked="item.done"
#change="complete[index].done = false">
</li>
new Vue({
el: "#app",
data() {
return {
tasks: [
{ description: 'Say Hello', done: true },
{ description: 'Review Code', done: false },
{ description: 'Read Emails', done: false },
{ description: 'Reply to Emails', done: false },
{ description: 'Wash The Dishes', done: true },
{ description: 'Stop Working', done: true },
]
};
},
computed : {
complete: {
get() {
return this.tasks.filter(task => task.done === true);
},
set(value) {
this.task.forEach((task, index) => {
let matched = value.find(({ description }) => description === task.description);
if(matched) {
this.task[index] = matched;
}
});
}
},
uncomplete: {
get() {
return this.tasks.filter(task => task.done === false);
},
set(value) {
this.task.forEach((task, index) => {
let matched = value.find(({ description }) => description === task.description);
if(matched) {
this.task[index] = matched;
}
});
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<h1>To-do List</h1>
<h2>Completed Tasks!</h2>
<ul>
<li
v-for="(item, index) in complete">
{{ item.description }}
<input
type="checkbox"
v-model="complete[index].done">
</li>
</ul>
<h2>Uncompleted Tasks!</h2>
<ul>
<li
v-for="(item, index) in uncomplete">
{{ item.description }}
<input
type="checkbox"
v-model="uncomplete[index].done">
</li>
</ul>
</div>

Why data returning from Laravel 9 api endpoint not showing in Vue UI?

I'm developing simple TodoList app using Laravle 9, VueJS 3, Vite bundler - all this built in tools
when creating Laravel fresh installation.
In app user can make CRUD operations with TodoItem and all user data saved on server, so
data preserved on page refresh.
Application almost finished, unless some strange bug: when I run app on local machine - all works perfectly, but when I deploy it on Heroku and open in browser - I see no todos in UI, although during installation some example todo rows already seeded in db.
I examined API - it returns data as expected:
[
{
"id": 67,
"text": "Thing1",
"is_done": false,
"is_urgent": false,
"created_at": "2022-08-24T09:16:37.000000Z",
"updated_at": "2022-08-24T09:16:37.000000Z"
},
{
"id": 68,
"text": "Buy milk",
"is_done": false,
"is_urgent": false,
"created_at": "2022-08-24T09:16:37.000000Z",
"updated_at": "2022-08-24T09:16:37.000000Z"
},
{
"id": 69,
"text": "Thing2",
"is_done": true,
"is_urgent": false,
"created_at": "2022-08-24T09:16:37.000000Z",
"updated_at": "2022-08-24T09:16:37.000000Z"
},
{
"id": 70,
"text": "Thing3",
"is_done": true,
"is_urgent": false,
"created_at": "2022-08-24T09:16:37.000000Z",
"updated_at": "2022-08-24T09:16:37.000000Z"
}
]
When I create new Todo in textbox request sends to server, and data saved on remote server - but on page refresh - I again get empty data in UI, althout i see in that data loaded
This is my App.vue
<template>
<div class="container mt-5" style="padding-left: 0 !important;">
<h3><span class="fw-bold text-warning">Simple</span> TodoList</h3>
</div>
<div class="container mt-4">
<div class="row">
<!-- Simple todos -->
<div class="col-md-6 py-3" style="border: 1px solid #ddd">
<p>Todos ({{ simpleTodos.length }})</p>
<ul>
<li :id="todo.id"
:key="todo.id"
:class="{ 'text-decoration-line-through': todo['is_done'], 'todo-item__link': true }"
v-for="todo in simpleTodos"
#click="contentVisible === todo.id ? contentVisible = false : contentVisible = todo.id">
{{ todo.text }}
</li>
</ul>
<input type="text" name="todo" id="todo.new" #keydown.enter="addTodo" placeholder="Type todo and press Enter" />
</div>
<!-- Urgent todos -->
<div class="col-md-6 py-3" style="border: 1px solid #ddd">
<p>Todos <span :class="{ 'text-danger': urgentTodos.length >= 3}">({{ urgentTodos.length }})</span></p>
<ul>
<li :id="todo.id"
:key="todo.id"
:class="{ 'text-decoration-line-through': todo['is_done'], 'todo-item__link': true }"
v-for="todo in urgentTodos"
#click="contentVisible === todo.id ? contentVisible = false : contentVisible = todo.id">
{{ todo.text }}
</li>
</ul>
</div>
</div>
</div>
</template>
<script>
import {getAllTodos, createTodo, removeTodo, toggleTodoCompleteStatus, toggleTodoUrgentStatus} from '../services/TodoService'
export default {
name: "App",
data() {
return {
allTodos: [],
contentVisible: false
}
},
mounted() {
this.getAllTodos();
},
computed: {
simpleTodos() {
return this.allTodos.filter(todo => todo['is_urgent'] === 0);
},
urgentTodos() {
return this.allTodos.filter(todo => todo['is_urgent'] === 1);
}
},
methods: {
getAllTodos()
{
getAllTodos()
.then(todos => {
console.log(todos)
this.allTodos = todos
})
.catch(err => {
alert('Error happened while fetching todos!');
console.error(err)
});
},
addTodo(e)
{
// return if value is empty
if(e.target.value.trim().length === 0)
return false;
const clientTodo = { text: e.target.value, is_done: 0, is_urgent: 0 }
createTodo(clientTodo).then(({ todo }) => {
this.allTodos.push(todo);
e.target.value = "";
});
},
}
}
</script>
<style scoped>
.todo-item__link {
cursor: pointer;
position: relative;
}
.todo-item__link .text-primary {
position: absolute;
padding-left: 10px;
}
.todo-item__link:hover {
text-decoration: underline;
}
</style>
I tring to use Vue Debug Tools - it shows empty allTodos list.
I don't unsderstand why this.getAllTodos() doesn't update state on mount
The problem is the is_done and is_urgent properties are Booleans in your API resonse, but your component is incorrectly comparing them to 0 and 1:
export default {
computed: {
simpleTodos() {
//return this.allTodos.filter(todo => todo['is_urgent'] === 0); ❌ Boolean is never a number
return this.allTodos.filter(todo => todo['is_urgent'] === false); ✅
// or
return this.allTodos.filter(todo => !todo.is_urgent); ✅
},
urgentTodos() {
//return this.allTodos.filter(todo => todo['is_urgent'] === 1); ❌ Boolean is never a number
return this.allTodos.filter(todo => todo['is_urgent'] === true); ✅
// or
return this.allTodos.filter(todo => todo.is_urgent); ✅
}
},
methods: {
addTodo(e) {
// const clientTodo = { text: e.target.value, is_done: 0, is_urgent: 0 } ❌ is_done and is_urgent should be Boolean
const clientTodo = { text: e.target.value, is_done: false, is_urgent: false } ✅
}
}
}
demo

VueJS: Passing data to methods using vuejs

This is my code for my html in App.vue file.
<b-form #submit="onSubmit">
<b-form-group>
**nested v-model binding**
<div v-for="(question, index) in questionsList" :key="question.question">
<h4>{{question.question}}</h4>
<div v-for="options in question.responses" :key="options.options">
<input
type="radio"
:name="'question'+index"
:value="options.options"
v-model="responses['question'+index]"
/>
{{options.options}}
<br />
</div>
</div>
<b-button variant="outline-primary" type="submit">Submit</b-button>
</b-form-group>
</b-form>
*** script ***
export default {
data() {
return {
responses: {},
questionsList: [
{
id: "1",
question: "What is the full form of HTTP?",
responses: [
{ options: "Hyper text transfer package" },
{ options: "Hyper text transfer protocol" }
],
},
{
id: "2",
question: "HTML document start and end with which tag pairs?",
responses: [
{ options: "HTML" },
{ options: "WEB" }
],
},
answersheet: {
q1: "Hyper text transfer protocol",
q2: "HTML"
},
methods: {
onSubmit(event) {
event.preventDefault();
var score = 0;
for (var key of Object.keys(this.responses)) {
console.log(key + " -> " + this.responses[key]);
//displays the answers of the users
**trying to compare the answers from my answersheet but keeps saying undefined**
if (this.responses[key] == this.answersheet[key]) {
score = score + 1;
}
}
displays score to console
console.log(score);
}
}
What I'm trying to do here is to calculate the number of correct answers and then send the result to an api, but my code won't work.
I'm still a noob with vuejs and this is my first project for my class.
I've made some points and made some changes on your code
You needed to make sure opening and closing brackets written
Check indexes and make sure you are comparing right values
Read documentation carefully and try to follow getting started instructions. It gives you quite good orientation.
Have fun
new Vue({
el: '#app',
data() {
return {
isSubmitted: false,
score: 0,
responses: {},
questionsList: [
{
id: "1",
question: "What is the full form of HTTP?",
responses: [
{ options: "Hyper text transfer package" },
{ options: "Hyper text transfer protocol" }
],
},
{
id: "2",
question: "HTML document start and end with which tag pairs?",
responses: [
{ options: "HTML" },
{ options: "WEB" }
],
},
],
answersheet: {
question0: "Hyper text transfer protocol",
question1: "HTML"
},
};
},
methods: {
tryAgain() {
this.responses = {};
this.score = 0;
this.isSubmitted = !this.isSubmitted;
},
onSubmit() {
for (var key of Object.keys(this.responses)) {
console.log(key + " -> " + this.responses[key]);
if (this.responses[key] == this.answersheet[key]) {
this.score++;
}
}
this.isSubmitted = !this.isSubmitted
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link href="https://unpkg.com/bootstrap#4.5.2/dist/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://unpkg.com/bootstrap-vue#2.16.0/dist/bootstrap-vue.css" rel="stylesheet" />
<script src="https://unpkg.com/bootstrap-vue#2.16.0/dist/bootstrap-vue.js"></script>
<div id="app">
<b-form #submit.prevent="onSubmit">
<b-form-group v-if="!isSubmitted">
<!-- nested v-model binding** -->
<div v-for="(question, index) in questionsList" :key="question.question">
<h4>{{question.question}}</h4>
<div v-for="options in question.responses" :key="options.options">
<input
type="radio"
:name="'question'+index"
:value="options.options"
v-model="responses['question'+index]"
/>
{{options.options}}
<br />
</div>
</div>
<b-button variant="outline-primary" type="submit">Submit</b-button>
</b-form-group>
<div v-else>
Your score: {{ score}}
<br>
<b-button variant="outline-primary" #click="tryAgain">Try Again</b-button>
</div>
</b-form>
</div>

How to render component data after page load on click

I am using vue js with laravel. I want to reload my data according to date on click.
My data from api is get according to date but in front it is not change
Here is under my app.js code
var socket = new Vue({
el: "#enrollment-app",
components: {
barChart
},
data: {
privateChannleData: null,
exam_type: null,
exam_id: null,
response_exam_data: [],
response_lap_data: [],
response_btn_list: [],
student_list: [],
lineChartData: {
lables: [],
options: [],
dataset: []
}
},
created() {
if (document.getElementById("exam_type"))
this.exam_type = document.getElementById("exam_type").value;
if (document.getElementById("exam_id"))
this.exam_id = document.getElementById("exam_id").value;
if (this.exam_type != null && this.exam_id != null)
this.getEnrollmentStatus();
},
methods: {
getEnrollmentStatus: function(date="null") {
var self = this;
var data_set = [];
var params = {
exam_type: document.getElementById("exam_type").value,
exam_id: document.getElementById("exam_id").value,
date:date,
};
console.log(params);
axios
.post("/api/get_enrollment_data", params)
.then(function(response) {
self.response_exam_data = response.data.data;
//console.log(self.response_exam_data.students[0]);
self.response_exam_data.students[0].forEach(function(ii, vv) {
self.student_list.push(ii);
});
self.response_btn_list=self.response_exam_data.articles[0];
self.lineChartData.dataset = {
labels: [
"Total Enrollment",
"Not Submitted",
"Submitted",
"Total Pass",
"Total Fail"
],
datasets: [
{
label: "Enrollment Data",
backgroundColor: "#f87979",
data: [
parseInt(self.response_exam_data.total_enrollment),
parseInt(self.response_exam_data.not_submitted),
parseInt(self.response_exam_data.submitted_count),
parseInt(self.response_exam_data.total_pass),
parseInt(self.response_exam_data.total_fail)
]
}
]
};
self.lineChartData.options = {
scales: {
yAxes: [
{
ticks: {
beginAtZero: true
}
}
]
},
responsive: true,
maintainAspectRatio: true
};
})
.catch(function(error) {
alert("Error. Try again after sometime.");
});
}
},
});
Here is under my html code.
<div id="enrollment-app">
<button v-for="(button, key) in response_btn_list" type="button" v-on:click="getEnrollmentStatus({{ button }})" class="btn btn-success btn-icon left-icon mr-10" :date="button">lap #{{ key+1 }} </button>
<div class="user-data">
<span class="name block capitalize-font">#{{student.name}}</span>
<span class="time block" style="width:400px;"> Status:- <span class="txt-primary">#{{student.status_text}} </span> Rank:- <span class="txt-primary">#{{student.My_rank}}</span> Time Taken:- <span class="txt-primary">#{{student.timeTaken}}</span><br/>
Result:- <span class="txt-primary">#{{student.final_result}}</span>
Total Marks:- <span class="txt-primary">#{{student.total_marks}}</span>
Obtained Marks:- <span class="txt-primary">#{{student.obtained_marks}}</span>
</span>
<div :class="student.status"></div>
<div class="clearfix"></div>
</div>
</div>
My resultant data on page load
image on laad data
My resultant data after click on button
data after click button
I only want to render data in front end..

Not able to access data variable in script but can in html

I have populated a data variable with an array, and can access its contents by using a v-for in the html, but I can't access any of the data in the variable within the script, and I don't know why.
var result = [{
"CatalogName": "Retro Doors",
"ItemName": "French Doors",
"ItemListPrice": "$461.00",
"ItemType": "Oak",
"ItemFeatures": [{
"Features": "Door Quantity",
"QTY": 2
},
{
"Features": "Door Hinges",
"QTY": 4
},
{
"Features": "Door Knobs",
"QTY": 1
},
{
"Features": "Door Looks",
"QTY": 1
},
{
"Features": "Glass Panes",
"QTY": 2
}
]
}];
new Vue({
el: '#app',
beforeCreate: function() {
console.log("Before Created");
},
created: function() {
console.log("Created");
this.GetItemsList();
},
beforeMount: function() {
console.log("Before Mount");
},
data: {
itemPriceList: []
},
methods: {
GetItemsList() {
this.itemPriceList = result;
}
},
mounted: function() {
console.log("Mounted");
console.log(this.ItemPriceList);
}
});
<script src="https://code.jquery.com/jquery-3.3.1.js" integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60=" crossorigin="anonymous"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.17/dist/vue.js"></script>
<div id="app">
{{ itemPriceList[0].CatalogName }}
<div v-for="item in itemPriceList">
{{ item.ItemName }}
<div v-for="items in item.ItemFeatures">
{{ items.Features }} : {{ items.QTY }}
</div>
</div>
</div>
You have a typo in a variable name inside mounted hook - used with capital I.
In data: itemPriceList
In mounted hook: this.ItemPriceList
Should be the same as defined inside data property.