Ng If with a boolean - to change the title of a page - javascript

In my page Stock I have several fields with a title named Title 1.
If I do a console.log I am on my first page !
ngOnInit() {
this.currentPortfolio = this.shrd.getData('currentPortfolio');
this.subPage = 'stocks';
this.sectionTitle = "";
this.pageTitle = "Options";
for (var i = 0; i < this.optionsDropdownFilters.length; i++) {
this.issuers.actionsGrouped[this.optionsDropdownFilters[i]] = [];
}
console.log("First page => Tile 1 : " + JSON.stringify(this.subPage = 'stocks'));
this.initiate();
}
In Google Chrome I have this:
Now, I click on the button Search in my page Stock...
I want to change Title1 to Title2.
If I do a console.log, I am on my second page
launchSearchSelected(t) {
this.searched = true;
this.dateNotValid = false;
this.dateDoesntExist = false;
if (this.search.equityDate.length == 0) {
this.dateDoesntExist = true
}
if (t == 'A' && this.search.equityOptionCode > 0 && this.search.equityDate.length > 0) {
this.launchSearchResult(t, this.search.equityOptionCode, this.search.equityDate);
} else if (t == 'I' && this.search.indexOptionCode.length > 0 && this.search.indexDate.length > 0) {
this.launchSearchResult(t, this.search.indexOptionCode, this.search.indexDate);
}
console.log("Second Page => Title 2 " + JSON.stringify(this.searched = true));
}
In my HTML, I don't understand how can I switch from one title to another with the boolean?
<ng-container *ngIf="subPage === 'stocks' ">
<div class="breadcrumb d-flex justify-content-between">
<h1>Title 1 </h1>
</div>
</ng-container>

It's hard to tell what the best way to proceed is without more information, but if you just want to change the title based on the this.subPage variable having the value "stocks" or not (like it seems you are attempting), then you can do this:
<ng-container>
<div class="breadcrumb d-flex justify-content-between">
<h1 *ngIf="subPage == 'stocks'">Title 1</h1>
<h1 *ngIf="subPage != 'stocks'">Title 2</h1>
</div>
</ng-container>

I have the solution:
<ng-container *ngIf="subPage === 'stocks' ">
<ng-container *ngIf="spinners.search === true ">
<div class="breadcrumb d-flex justify-content-between">
<h1>Title 1 </h1>
</div>
</ng-container>
</ng-container>
<ng-container *ngIf="subPage === 'stocks' ">
<ng-container *ngIf="spinners.search === false ">
<div class="breadcrumb d-flex justify-content-between">
<h1>Title 2 </h1>
<button (click)="goBack()" class="btn btn-primary"> Back
</button>
</div>
</ng-container>
</ng-container>

Related

How do I get this div to show again using JavaScript

I have made a TODO app and added a counter to keep a count of the items in the list. If the counter hits zero, I've set it to re-show a message 'You currently have no tasks. Use the input field above to start adding.'
if(count === 0){
noTasksText.classList.remove('d-none');
}
In the console I print out the div and it doesn't have d-none in the class list any more which is what I want, however, in the actual DOM it does.
Here is a full example - https://codepen.io/tomdurkin/pen/LYdpXKJ?editors=1111
I really can't seem to work this out. I can't seem to interact with that div when the counter becomes zero, however I can get console logs etc to show when expected.
Any help would be appreciated!
const mainInput = document.querySelector('#main-input');
const todoContainer = document.querySelector('#todo-container');
const errorText = document.querySelector('#js-error');
const noTasksText = document.querySelector('.js-no-tasks')
let tasks = [];
let count = 0;
// focus input on load
window.onload = () => {
mainInput.focus();
const storedTasks = JSON.parse(localStorage.getItem('tasks'));
if (storedTasks != null && storedTasks.length > 0) {
// set count to number of pre-existing items
count = storedTasks.length
// hide the 'no tasks' text
noTasksText.classList.add('d-none');
// overwrite tasks array with stored tasks
tasks = storedTasks;
tasks.forEach(task => {
// Build the markup
const markup = `
<div class="js-single-task single-task border-bottom pt-2 pb-2">
<div class="row">
<div class="col d-flex align-items-center js-single-task-name">
<h5 class="mb-0" data-title="${task}">${task}</h5>
</div>
<div class="col d-flex justify-content-end">
<button class="js-remove-task d-block btn btn-danger">Remove Item</button>
</div>
</div>
</div>`;
// Append it to the container
todoContainer.innerHTML += markup;
});
} else {
if (noTasksText.classList.contains('d-none')) {
noTasksText.classList.remove('d-none');
}
}
};
// event listener for 'enter on input'
mainInput.addEventListener("keydown", e => {
// if error is showing, hide it!
if (!errorText.classList.contains('d-none')) {
errorText.classList.add('d-none');
}
if (e.key === "Enter") {
// Get the value of the input
let inputValue = mainInput.value;
if (inputValue) {
// Build the markup
const markup = `
<div class="js-single-task border-bottom pt-2 pb-2">
<div class="row">
<div class="col d-flex align-items-center js-single-task-name">
<h5 class="mb-0" data-title="${inputValue}">${inputValue}</h5>
</div>
<div class="col d-flex justify-content-end">
<button class="js-remove-task d-block btn btn-danger">Remove Item</button>
</div>
</div>
</div>`;
// hide 'no tasks' text
noTasksText.classList.add('d-none');
// Append it to the container
todoContainer.innerHTML += markup;
// Push value to 'tasks' array
tasks.push(inputValue);
// Put in localStorage
textTasks = JSON.stringify(tasks);
localStorage.setItem("tasks", textTasks);
// Reset the value of the input field
mainInput.value = '';
// add 1 to the count
count++
} else {
// Some very basic validation
errorText.classList.remove('d-none');
}
}
});
// remove task
todoContainer.addEventListener('click', (e) => {
// Find the button in the row that needs removing (bubbling)
const buttonIsDelete = e.target.classList.contains('js-remove-task');
if (buttonIsDelete) {
// Remove the HTML from the screen
e.target.closest('.js-single-task').remove();
// Grab the name of the single task
let taskName = e.target.closest('.js-single-task').querySelector('.js-single-task-name h5').getAttribute('data-title');
// filter out the selected word
tasks = tasks.filter(item => item != taskName);
textTasks = JSON.stringify(tasks);
localStorage.setItem("tasks", textTasks);
// update counter
count--
// check if counter is zero and re-show 'no tasks' text if true
if (count === 0) {
noTasksText.classList.remove('d-none');
console.log(noTasksText);
}
}
});
body {
background: #e1e1e1;
}
<div class="container">
<div class="row d-flex justify-content-center mt-5">
<div class="col-10 col-lg-6">
<div class="card p-3">
<h2>To dos</h2>
<p>
Use this app to keep a list of things you need to do
</p>
<input class="form-control" id="main-input" type="text" placeholder="Type your todo and hit enter..." class="w-100" />
<small id="js-error" class="text-danger d-none">
Please type a value and press enter
</small>
<hr />
<h4 class="mb-5">Your 'To dos'</h4>
<div id="todo-container">
<!-- todos append in here -->
<div class="js-no-tasks">
<small class="d-block w-100 text-center mb-3">
<i>
You currently have no tasks. Use the input field above to start adding
</i>
</small>
</div>
</div>
</div>
<!-- /card -->
</div>
</div>
</div>
Upon setting innerHTML by using += innerHTML the node noTasksText is lost, because browser processes the whole new set innerHTML and creates new objects. You can either retrieve noTasksText again after that, or append nodes using todoContainer.appendChild. I forked your pen and solved it with the latter solution.
https://codepen.io/aghosey/pen/wvmGwWd
You can do the following, it will work (here innerHTML is changing the DOM, so I added an extra function to recalculate elements after DOM is changed due to innerHTML):
var mainInput = document.querySelector("#main-input");
var todoContainer = document.querySelector("#todo-container");
var errorText = document.querySelector("#js-error");
var noTasksText = document.querySelector(".js-no-tasks");
let tasks = [];
let count = 0;
function getAllElements() {
mainInput = document.querySelector("#main-input");
todoContainer = document.querySelector("#todo-container");
errorText = document.querySelector("#js-error");
noTasksText = document.querySelector(".js-no-tasks");
}
// focus input on load
window.onload = () => {
mainInput.focus();
var storedTasks = JSON.parse(localStorage.getItem("tasks"));
if (storedTasks != null && storedTasks.length > 0) {
// set count to number of pre-existing items
count = storedTasks.length;
// hide the 'no tasks' text
noTasksText.classList.add("d-none");
// overwrite tasks array with stored tasks
tasks = storedTasks;
tasks.forEach((task) => {
// Build the markup
const markup = `
<div class="js-single-task single-task border-bottom pt-2 pb-2">
<div class="row">
<div class="col d-flex align-items-center js-single-task-name">
<h5 class="mb-0" data-title="${task}">${task}</h5>
</div>
<div class="col d-flex justify-content-end">
<button class="js-remove-task d-block btn btn-danger">Remove Item</button>
</div>
</div>
</div>`;
// Append it to the container
todoContainer.innerHTML += markup;
getAllElements();
});
} else {
if (noTasksText.classList.contains("d-none")) {
noTasksText.classList.remove("d-none");
}
}
};
// event listener for 'enter on input'
mainInput.addEventListener("keydown", (e) => {
// if error is showing, hide it!
if (!errorText.classList.contains("d-none")) {
errorText.classList.add("d-none");
}
if (e.key === "Enter") {
// Get the value of the input
let inputValue = mainInput.value;
if (inputValue) {
// Build the markup
const markup = `
<div class="js-single-task border-bottom pt-2 pb-2">
<div class="row">
<div class="col d-flex align-items-center js-single-task-name">
<h5 class="mb-0" data-title="${inputValue}">${inputValue}</h5>
</div>
<div class="col d-flex justify-content-end">
<button class="js-remove-task d-block btn btn-danger">Remove Item</button>
</div>
</div>
</div>`;
// hide 'no tasks' text
noTasksText.classList.add("d-none");
// Append it to the container
todoContainer.innerHTML += markup;
getAllElements();
// Push value to 'tasks' array
tasks.push(inputValue);
// Put in localStorage
textTasks = JSON.stringify(tasks);
localStorage.setItem("tasks", textTasks);
// Reset the value of the input field
mainInput.value = "";
// add 1 to the count
count++;
} else {
// Some very basic validation
errorText.classList.remove("d-none");
}
}
});
// remove task
todoContainer.addEventListener("click", (e) => {
// Find the button in the row that needs removing (bubbling)
const buttonIsDelete = e.target.classList.contains("js-remove-task");
if (buttonIsDelete) {
// Remove the HTML from the screen
e.target.closest(".js-single-task").remove();
// Grab the name of the single task
let taskName = e.target
.closest(".js-single-task")
.querySelector(".js-single-task-name h5")
.getAttribute("data-title");
// filter out the selected word
tasks = tasks.filter((item) => item != taskName);
textTasks = JSON.stringify(tasks);
localStorage.setItem("tasks", textTasks);
// update counter
count--;
// check if counter is zero and re-show 'no tasks' text if true
if (count === 0) {
noTasksText.classList.remove("d-none");
console.log(noTasksText);
}
}
});
body {
background: #e1e1e1;
}
<div class="container">
<div class="row d-flex justify-content-center mt-5">
<div class="col-10 col-lg-6">
<div class="card p-3">
<h2>To dos</h2>
<p>
Use this app to keep a list of things you need to do
</p>
<input class="form-control" id="main-input" type="text" placeholder="Type your todo and hit enter..." class="w-100" />
<small id="js-error" class="text-danger d-none">
Please type a value and press enter
</small>
<hr />
<h4 class="mb-5">Your 'To dos'</h4>
<div id="todo-container">
<!-- todos append in here -->
<div class="js-no-tasks">
<small class="d-block w-100 text-center mb-3">
<i>
You currently have no tasks. Use the input field above to start adding
</i>
</small>
</div>
</div>
</div>
<!-- /card -->
</div>
</div>
</div>

How to make if statement rerender component svelte

Here is what I have for my script :
function changeCart(subCat)
{
let addedCat = {id: subCat._id,name: subCat.name, name_categorie: subCat.name_categorie}
let exist = $cart.some(element => {
if(element.id === addedCat.id)
{
return true
}
})
if(exist)
{
$cart.some(element => {
if(element.id === addedCat.id)
{
$cart.splice($cart.indexOf(element, 1))
return true
}
})
}
else
{
$cart = [...$cart, addedCat]
}
console.log($cart)
}
and here is my html :
{#each subCategories as subCategories}
{#if ($cart.indexOf(subCategories.name) > -1)}
<div class="media ali list-group-item list-group-item-action clique selected" on:click={() => changeCart(subCategories)}>
<Management/>
<div class="media-body" >
<h4 class="media-heading">{subCategories.name}</h4>
</div>
</div>
{:else}
<div class="media ali list-group-item list-group-item-action clique" on:click={() => changeCart(subCategories)}>
<Management/>
<div class="media-body" >
<h4 class="media-heading">{subCategories.name}</h4>
</div>
</div>
{/if}
{/each}
I want to change this line :
{#if ($cart.indexOf(subCategories.name) > -1)}
The goal is to check if an object is already in $cart like the script part already do but I don't know how to make the modification for the if statement in my html
You can simply use the class:<name> Svelte directive. To add better readability, you could also make use of the new-ish #const block directive:
{#each subCategories as subCategory}
{#const selected = $cart.some(element => element.id === subCategory.id)}
<div class:selected class="media ali list-group-item list-group-item-action clique" on:click={() => changeCart(subCategory)}>
<Management/>
<div class="media-body" >
<h4 class="media-heading">{subCategory.name}</h4>
</div>
</div>
{/each}
Note: also changed the name of the currently iterated value to subCategory (don't name the iterator the same as the iteratee).
I found the solution : this is what I've done :
Script part :
function changeCart(subCat)
{
let addedCat = {id: subCat._id,name: subCat.name, name_categorie: subCat.name_categorie}
let exist = checkIfExist(subCat)
if(exist >= 0)
{
$cart = $cart.filter(item => item.id !== subCat._id)
}
else
{
$cart = [...$cart, addedCat]
}
console.log($cart)
}
function checkIfExist(cat)
{
for( let i = 0; i < $cart.length; i++)
{
if($cart[i].id == cat._id){
return i
}
}
return -1
}
and the html part :
{#key $cart}
{#each subCategories as subCategory}
<div class={`media ali list-group-item list-group-item-action ${checkIfExist(subCategory) >= 0 ? "selected" :""} clique`} on:click={() => {changeCart(subCategory)}}>
<Management/>
<div class="media-body">
<h4 class="media-heading">{subCategory.name}</h4>
</div>
</div>
{/each}
{/key}

Cant make useful a button inserted in innerHTML for one function

I have one button that shows all my products in the webpage, each product is loaded from an array and inserted with innerHTML, each product is inserted with one button, i tried to assing one function for those buttons, but nothing happens:
Show.addEventListener('click', () => {
flag = flag + 1
if (flag == 2) {
document.getElementById('ItemsID').disabled = true
}
console.log(ItemsID.options[ItemsID.selectedIndex].value)
if (ItemsID.options[ItemsID.selectedIndex].value == "Vuelos") {
document.getElementById('ShowItems').disabled = true
VUELOSPROMOCIONES.forEach((VUELOSPROMOCIONES, indice) => {
div_Vuelos.innerHTML += `
<div class="card" id="persona${indice + 1}" style="width: 18rem;">
<div class="card-body">
<h5 class="card-title">Vuelo Promocional ${indice + 1}</h5>
<p>Origen: ${VUELOSPROMOCIONES.origen}</p>
<p>Destino: ${VUELOSPROMOCIONES.destino}</p>
<p>Fecha Ida: ${VUELOSPROMOCIONES.FechaIda}</p>
<p>Fecha Vuelta: ${VUELOSPROMOCIONES.FechaVuelta}</p>
<p>Precio: ${VUELOSPROMOCIONES.precio}</p>
</div>
</div>
**<button id="Enviar">Click me</button>**
`
})
} else if (ItemsID.options[ItemsID.selectedIndex].value == "Autos") {
PROMOCIONESAUTOS.forEach((PROMOCIONESAUTOS, indice) => {
document.getElementById('ShowItems').disabled = true
div_Autos.innerHTML += `
<div class="card" id="Autos Disponibles ${indice + 1}" style="width: 18rem;">
<div class="card-title">Persona ${indice + 1}</h5>
<p>Modelo: ${PROMOCIONESAUTOS.modelo}</p>
<p>Marca: ${PROMOCIONESAUTOS.marca}</p>
<p>Color: ${PROMOCIONESAUTOS.color}</p>
</div>
</div>
<button id="Enviar">Click me</button>
`
})
}
})
if i insert the same button in the html, it works with the same id

v-show does not work as I expected in my code

First I get data set from database using API and add a custom field called "isShare" and add value "false" in the initial state, then I iterate these data using v-for. Then I wanted to change the value of the "isShare" depending on the click event of another element.
I tired using v-show and v-if both. But in both cases, I couldn't get the result I wanted.
This is the code I used to get data from database and add a custom field called "isShare"
loadLessons() {
axios.get('/api/find/non_auth_get_lessons')
.then(({data}) => {
(this.lessons = data)
this.lesson_images = []
this.lessons.forEach(lesson => {
this.lesson_images.push(`${window.location.protocol + '//'
+ window.location.hostname}/lesson_covers/${lesson.lesson_cover_image}`)
lesson.isShare = false
});
},
(error) => {
this.loadLessons()
}
)
},
This is how I iterate data.
<carousel-3d class="slider_container lesson_container" :disable3d="true"
:space="320" :clickable="false" :controls-visible="true" style="height: 100%">
<slide class="card m-1 lma_view bg-white" v-for="(lesson, index) in lessons" :index="index" :key="index" >
<div class="card_img_wrapper" >
<img :src="lesson_images[index]" class="card-img-top" alt="..." v-
if="lesson.lesson_cover_image !== null" draggable="false">
</div>
<div class="card-body" >
<h5 class="card-title welcome_page_card_title" v-
html="$options.filters.truncate(lesson.lesson_title, 25, '...')"></h5>
<div class=" d-flex flex-column welcome_page_lesson_details">
<small class="card-text">Subject : <span class="text-muted">{{
lesson.subject | truncate(30, '...') }}</span></small>
<small class="card-text">Material Type : <span class="text-muted">{{
lesson.meterial_type === '1' ? 'Text based' : (lesson.meterial_type ===
'2' ? 'Video based' : 'Document based') }}</span></small>
<small class="card-text">Language : <span
class="text-muted">{{ lesson.language === '1' ? 'Sinhala' :
(lesson.language === '2' ? 'English' : 'Tamil') }}</span></small>
</div>
<hr/>
<div class="text-center">
View
<span class=""><i class="fas fa-share-alt share_icon"
#click="sharePopup(lesson, index)"></i></span>
<!--<div class="share_options" v-show="lesson.isShare"></div>-->
<div class="share_options">{{lesson.isShare}}</div>
<span class="badge pull-right" :class="lesson.access_type === '1' ?
'badge-success' :
(lesson.access_type === '2' ? 'badge-warning' : 'badge-info')">
{{ lesson.access_type === '1' ? 'Free'
: (lesson.access_type === '2' ? 'Restricted' : 'Paid') }}
</span>
</div>
</div>
</slide>
</carousel-3d>
When I click on the element witch has "share_icon" class I need to change the value of "isShare"
When I clicked on the "share_icon" it trigger the sharePopup function and changes the value of "isShare" but does not render
sharePopup(lesson, index){
lesson.isShare = !lesson.isShare;
}
You should access your array by the given index which is passed as parameter as follows:
sharePopup(lesson, index){
this.lessons[index].isShare = !lesson.isShare;
this.$set(this.lessons,index, this.lessons[index])
}
learn more about $set function here

Angular ng-show if in array

I have a ng-repeat for article comments, that looks like this:
<div ng-repeat="comment in comments">
<li class="item" ng-class-even="'even'">
<div class="row">
<div class="col">
<i class="icon ion-person"></i> {{ comment.user.first_name }} {{ comment.user.last_name }}
<i class="icon ion-record"></i> {{ comment.created_at }}
</div>
<!-- TODO: this needs to be an ng-if admin -->
<div ng-show="hasRole(comment.user)" class="col right">
<i class="icon ion-record admin"></i> Admin
</div>
</div>
<div class="row">
<div class="col">
<p>{{ comment.text }}</p>
</div>
</div>
</li>
</div>
I am trying to show this part only if the user is an admin:
<div ng-show="hasRole(comment.user)" class="col right">
<i class="icon ion-record admin"></i> Admin
</div>
I have tried to set that up following the answers here.
So I made a function in my controller:
$scope.hasRole = function(roleName) {
return $scope.comments.user.roles.indexOf(roleName) >= 0;
}
But it returns -1 every time, even when the user is an admin. My data looks like this:
1:Object
$$hashKey: "object:28"
article_id:"2"
created_at:"2016-05-12 12:19:05"
id:6
text:"someCommentText"
updated_at:null
user:Object
active:"1"
created_at:null
first_name:"admin"
id:1
last_name:"admin"
roles:Array[1]
0:Object
created_at:null
id:1
name:"Admin"
parent_id:null
pivot:Object
slug:"admin"
Use this in your HTML
<div ng-show="hasAdminRole(comment.user.roles)" class="col right">
<i class="icon ion-record admin"></i> Admin
</div>
this is the method to determine that the user belongs to the admin role or not.
$scope.hasAdminRole = function(roles) {
var isAdmin = false;
for(var i = 0; i < roles.length; i++) {
if (roles[i].name == 'Admin') {
isAdmin = true;
break;
}
}
return isAdmin;
}
Perhaps you have an error on this line?
var indexOfRole = $scope.comments.indexOf(user.roles);
You are looking here to see if the list of roles for this users exists within the array of comments.
Maybe you need to just check in the actual user.roles array and see if there is an Admin role there? Something like:
$scope.hasRole = function(user) {
for (var i = 0; i < user.roles.length; i++) {
if (user.roles[i].slug === 'admin') { return true; }
}
return false
}
That's because it's an object, you can fetch the index of only array. In the link that you provided is an array.

Categories