Meteor chatbox html is stuck in string form - javascript

I'm writing a chat box into my web app and HTML posts into the chat div are not showing like I expected them too. They are displaying in string form, I would like HTML to render in chat. Not sure why they are in string form, I'm not filtering the strings at all. How could I get the HTML to be rendered?
HTML:
<div *ngFor="let x of serverObj.values">
<div *ngFor="let y of x.shouts">
<p>
<span style="font-family: initial; font-size: x-small; font-
weight: bold;">{{y.shoutTime}}</span>
<span style="font-size: small; font-weight: bold;">{{y.shoutUser}}</span>
<span>: {{y.shoutContent}}</span>
</p>
</div>
</div>
<form name="shoutbox">
<textarea
style="color: black;"
id="shoutbox_input"
#textArea
(keyup.enter)="serverObj.addShout(displayName(), textArea.value)"
(keyup.enter)="textArea.value = ''"
></textarea>
<p><button id="shout_submit_button" type="button" (click)="serverObj.addShout(displayName(), textArea.value)">Sumbit</button></p>
</form>
Data Interface:
shouts: [{
shoutUser: string;
shoutContent: string;
shoutTime: Date;
}];
Server Class (where shouts are being added to database):
public addShout(user: string, content: string): void{
//setting the proper time
function addZero(i) {
if (i < 10) {
i = "0" + i;
}
return i;
}
function nonMilitary(j){
return ((j + 11) % 12 + 1);
}
function amPM(k){
if(k >= 12){
return "PM";
}
else return "AM";
}
let date = new Date();
let hours = date.getHours();
let time = "(" + addZero(nonMilitary(hours)) + ":" +
addZero(date.getMinutes()) + " " + amPM(hours) + ")";
//TODO add id calling variable to hold the current day.
let day = ServerData.findOne({id: "Mark"});
ServerData.update(day._id, { $push: { shouts: { shoutUser: user,
shoutContent: content, shoutTime: time }}});
}
Chat OutPut:
(11:58 AM) PizzaLord : <img src="https://www.shabboshouse.org/wp-
content/uploads/2015/11/rocks2.jpg"/>
(12:03 PM) PizzaLord : shout
(12:08 PM) PizzaLord : Google.com website
Thanks for your help.

As explained in this article, interpolation causes the content to be escaped, and the HTML tags to be displayed as plain text.
Instead of using interpolation:
<span>: {{y.shoutContent}}</span>
you can set the innerHTML property with data binding, as shown in this stackblitz:
<span [innerHTML]="': ' + y.shoutContent"></span>

Related

Angular Count Becomes 0 When Page is Refreshed

In my code, I have a page where the user can scan some labels and gets add to a list. Every time the user scan a label, total and package count above the list gets updated. But when I refresh the page, the counts become 0 as if there is no label on the list. Here is my code. What should I do?
HTML:
<div fxLayout="row" fxLayoutAlign="start center">
<span class="pr-4">{{'Paket : ' + packageCount }}</span>
<span>{{'Adet : ' + totalCount }}</span>
</div>
TS:
constructor(){
this.calculateRemainingValue();
}
addPackage(response: IKoli, barcodeNumber: string): boolean {
this.calculateRemainingValue();
this.isSaved = false;
this.fg1.reset();
return true;
}
calculateRemainingValue() {
if (this.dataSource.data) {
this.packageCount = this.dataSource.data.length;
let totalWeight = 0;
this.dataSource.data.forEach((x) => (totalWeight += Number(x.PaketAdedi)));
this.totalCount = totalWeight;
}
}
How I know this is normal behaviour of angular.
You must save the counter in some place, for example database or you could save it as cookie or save it in localStorage/sessionStorage.
Hope I helped you!

Adding more and more <timepicker> issue. if one gets changed it changes all of them

I have a little problem, I repeat timepicker with *ngFor, but it's not working properly if I changed the time in one of them, it changes in all. And all have a different id. AN IDEA TO MAKE THE WORk PROPERLY?`
COMPONENT.HTML :
<div id="schedule" *ngFor="let i of Arr(num).fill(1)"
style="display: -webkit-inline-flex">
<timepicker id="timer" class="schedulItem" style="margin-top:-28px"
[(ngModel)]="mytime" [showMeridian]="isMeridian"
[minuteStep]="mstep" (ngModelChange)="changed()">
</timepicker>
<button (click)="addSchedule()"> + </button>
</div>
COMPONENT.TS:
Arr = Array; //Array type captured in a variable
num:number = 1;
mytime: Date;
addSchedule() {
this.num = this.num + 1 ;
var length = document.querySelectorAll('.schedul').length
var time = document.getElementById("timer");
time.id += length;
}
changed(): void {
var time = this.mytime.getHours() + ":" + this.mytime.getMinutes();
console.log(time);
}
I found the problem! the model was the problem [(ngModel)]="mytime". All time pickers to the same model and one gets changed it changes all of them.

The data binding between html element property and script value not synchronized

Problem description:
There is an availability calendar which displays whether a person is busy on a particular slot (each day is divided to two slots). This state is stored in the isSlotFree boolean 2d array (this array is of size 31 x 2). Initially, all values in this array are initialized to true. Then, a http get request is made to a server requesting the busy dates. Once they are received, the function setIsSlotFree() is called to set the appropriate values in the array to false. In the view (HTML file) there is a <td> element for each slot. Each of these elements update their color (using class styles) based on the boolean value stored in the relevant index of the array. The problem is that the html page does not reflect the changes made to the array after calling the setIsSlotFree() function. (ie. the html elements still see all values as true). However, when I print the array in the console right after the get request, it has changed the appropriate values to false. When any event is triggered, then only the view is updated to the correct values. What is the problem here?
Following are the relevant parts of the component.ts file
export class CalendarComponent implements OnInit {
viewDate: Date;
isSlotFree: boolean[][] = [
[true, true]
];
constructor(private http: HttpClient) {
}
ngOnInit() {
this.viewDate = new Date();
var i: number;
var j: number;
for (i = 1; i < 31; i++) {
this.isSlotFree.push([true, true]);
}
let p = new HttpParams().set('month', (this.viewDate.getMonth() + 1).toString());
this.http.get < busyDateResponse[] > ("http://localhost:51967/api/stylists/getBusyDates", {
params: p
}).subscribe(res => {
this.setIsSlotFree(res);
});
this.x = true;
console.log(this.isSlotFree);
this.viewDate = new Date();
}
setIsSlotFree(res: busyDateResponse[]): void {
var busy_date: busyDateResponse;
for (busy_date of res) {
var temp: number = (busy_date.slot == 'm') ? 0 : 1;
this.isSlotFree[busy_date.day - 1][temp] = false;
}
}
}
interface busyDateResponse {
$id: string;
day: number;
month: number;
year: number;
slot: string;
}
Following shows the relevant parts of the component.html file
<ng-template #cellTemplate let-day="day" let-locale="locale">
<div class="cal-cell-top">
<div class="cal-day-number w3-xlarge">{{ day.date | calendarDate:'monthViewDayNumber':locale }}</div>
<br>
</div>
<div *ngIf="day.inMonth && day.isFuture">
<table style="width:100%">
<tr>
<td class="calendar-slot" [ngClass]="{'w3-green': isSlotFree[day.date.getDate()-1][0], 'w3-red': !isSlotFree[day.date.getDate()-1][0]}">{{isSlotFree[day.date.getDate()-1][0]}}Morning</td>
<mat-checkbox (change)="editSelectedSlots($event)" [checked]="isSelectedSlot(day.date.getDate() + '_' + day.date.getMonth() + '_' + day.date.getFullYear() + '_m')?true:false" [id]="day.date.getDate() + '_' + day.date.getMonth() + '_' + day.date.getFullYear() + '_m'"
*ngIf="isSlotFree[day.date.getDate()-1][0]"></mat-checkbox>
</tr>
<tr>
<td class="calendar-slot" [ngClass]="{'w3-green': isSlotFree[day.date.getDate()-1][1], 'w3-red': !isSlotFree[day.date.getDate()-1][1]}">{{isSlotFree[day.date.getDate()-1][1]}}Evening</td>
<mat-checkbox (change)="editSelectedSlots($event)" [checked]="isSelectedSlot(day.date.getDate() + '_' + day.date.getMonth() + '_' + day.date.getFullYear() + '_e')?true:false" [id]="day.date.getDate() + '_' + day.date.getMonth() + '_' + day.date.getFullYear() + '_e'"
*ngIf="isSlotFree[day.date.getDate()-1][1]">
</mat-checkbox>
</tr>
</table>
</div>
</ng-template>
<div>
<mwl-calendar-month-view [viewDate]="viewDate" [events]="events" (eventClicked)="eventClicked($event)" (dayClicked)="dayClicked($event)" [cellTemplate]="cellTemplate" [refresh]="refresh">
</mwl-calendar-month-view>
<div class="w3-center">
<button mat-raised-button>Make booking</button>
</div>
</div>
Please note that <mwl-calendar-month-view> utilizes the ng-template to generate cells in a calendar.
Well I finally found the solution after reading a lot about change detection in angular. The change detection strategy is executed before running the setIsSlotFree() function.Even though the values in the array are modified, the change detection strategy is not executed when the array values are changed by this function. Therefore, change detection needs to be executed manually after writing all the changes to the array. This can be done using ChangeDetectorRef.detectChanges() at the end of the setIsSlotFree() function.
If the constructor for the component is constructor(private http: HttpClient, private ref: ChangeDetectorRef) then, the isSlotFree() function would look like,
setIsSlotFree(res:busyDateResponse[]):void {
var busy_date:busyDateResponse;
for(busy_date of res) {
var temp:number = (busy_date.slot=='m')?0:1;
this.isSlotFree[busy_date.day-1][temp] = false;
}
this.ref.detectChanges();
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

Display localstorage in input on load

I have a small web calculator which calculates time. My mobile browser gets rid of all data when I've minimised/closed the mobile broswer for a few minutes or on a page refresh so I've made a button which can reload all previous data and displays as text.
I want to get rid of the "Get old data" button and just have the page reload with all the values displayed in the input box as they were before the page refresh.
I've been thinking an onload event in the input box would work but as i understand this is not possible.
HTML
<body onload="getreload()">
<p>Please enter minutes</p>
<input type="text" id="etime">
<br>
<p>Please enter time in 24 hour format (eg. 15:00)</p>
<input type="text" id="stime">
<br>
<br>
<button onclick="myFunction()">Calculate</button>
<p id="finishtime">
<br>
<br>
<button onclick="getreload()">Get old data</button>
<p id="finishtime2">
<p id="mintime2">
</body>
Javascript
function myFunction() {
function converToMinutes(s) {
var c = s.split(':');
return parseInt(c[0]) * 60 + parseInt(c[1]);
}
function parseTime(s) {
var seconds = parseInt(s) % 60;
return Math.floor(parseInt(s) / 60) + ":" + ((seconds < 10)?"0"+seconds:seconds);
}
var endTime = document.getElementById("etime").value;
var startTime = converToMinutes(document.getElementById("stime").value);
var converted = parseTime(startTime - endTime);
document.getElementById('finishtime').innerHTML = "You will finish your break at " + converted;
if (typeof(Storage) !== "undefined") {
localStorage.setItem("convertedTime", converted);
localStorage.setItem("endTimeReload", endTime);
} else {
// Sorry! No Web Storage support
}
}
function getreload() {
var convertedTime = localStorage.getItem("convertedTime");
document.getElementById('finishtime2').innerHTML = "End of break time: " + convertedTime;
var endTimeReload = localStorage.getItem("endTimeReload");
document.getElementById('mintime2').innerHTML = "Minutes till next client: " + endTimeReload;
}
You are mostly there, but you are not restoring correctly and not saving the startTime.
Here is a fiddle with everything you need:
https://jsfiddle.net/22ej8scw/
Restore like this. (I also changed how it is saved)
function getreload() {
var startTime = localStorage.getItem("startTime");
document.getElementById("stime").value = startTime;
var endTimeReload = localStorage.getItem("endTimeReload");
document.getElementById("etime").value = endTimeReload;
if (startTime && endTimeReload)
myFunction();
}
So after you've calculated a time, you want those values to be there if you refresh the page?
When you calculate, save all the values in localstorage, then when the page loads (body element's 'onload') set the input boxes values to the corresponding localstorage ones (checking to make sure those values exist first)

Error with JavaScript Object

The code only processes the last string of the object and then proceeds based off of that one and doesn't display a child's name even if their birthday does match today's date when that child's string of data is not the last one entered into the object. I need some advice or help in how to make the javascript find each person whose birthday matches the date and display them instead of just looking at the last child's data
var studentProfile = [];
var index=0;
function saveProfile()
{
studentProfile[index] = {
firstName: document.getElementById("txtFirstName").value,
surname: document.getElementById("txtSurname").value,
birthday: document.getElementById("txtBirthday").value,
contactInfomation: document.getElementById("txtContactInfomation").value,
medicalInformation: document.getElementById("txtMedicalInformation").value,
}
index = index + 1;
localStorage.setItem("students", JSON.stringify(studentProfile));
}
function displayProfile()
{
for (var i = 0; i<studentProfile.length; i++) {
alert("The Student's Name is " + studentProfile[i].firstName + " " + studentProfile[i].surname + ".");
alert("The Student's Birthday is " + studentProfile[i].birthday + ".");
alert("The Student's Contact Information is: " + studentProfile[i].contactInfomation + ".");
alert("The Student's Medical Information is: " + studentProfile[i].medicalInformation) + ".";
}
}
function clearData()
{
document.getElementById("txtFirstName").value = "";
document.getElementById("txtSurname").value = "";
document.getElementById("txtBirthday").value = "";
document.getElementById("txtContactInfomation").value = "";
document.getElementById("txtMedicalInformation").value = "";
}
function birthday()
{
//state all the variables for the program and convert the JSON string from the register js back into an object
var studentProfile = new Object();
var studentBirthday;
var bdayMonth, bdayDay;
var birthDate = new Date();
var today = new Date();
var todayMonth;
var todayDay;
studentProfile = JSON.parse(localStorage.getItem("students"));
// this variable is for the birthday picture to disappear if there are no birthdays, its used later on in the code
var BirthdayBorder = document.getElementById("BirthdayBorder");
// this variable is for the text to change position if there are no birthdays, its used later on in the code
var txtbirthday = document.getElementById("txtContainer");
//I had an alert here to see if the javascript was accurately able to convert the string back into an object and after this is the actual programs code
for (var i = 0; i < studentProfile.length; i++)
{
//here is where the variables regarding the date were specified and extracted from the object that was converted
bdayMonth = studentProfile[i].birthday.substring(0,2);
bdayDay = studentProfile[i].birthday.substring(3,5);
todayMonth = today.getMonth()+1;
todayDay = today.getDate();
//this is where the comparison part of the code starts, basically the birthday entered by the user is compared with today's date
if ((bdayDay == todayDay) && (bdayMonth == todayMonth))
{
//if the dates are equal to one another then the student's firstname is determined and displayed as an output in the html
document.getElementById("birthdays").innerHTML = studentProfile[i].firstName;
BirthdayBorder.style.opacity = "100";
BirthdayBorder.style.marginTop = "0px";
txtbirthday.style.marginTop = "144px";
}
else
{
//the program has determined that there are no birthdays today and will display the text instead of a student's name
document.getElementById("birthdays").innerHTML = "No Birthdays Today! ;)";
//this is the styling part for the birthday border to be transparent and moved to a place where it isn't affecting the website's margins and the text is moved to look better than being in empty space
BirthdayBorder.style.opacity = "0";
BirthdayBorder.style.marginTop = "-1000px";
txtbirthday.style.marginTop = "-50px";
}
}
}
okay here is the requested other information
html:
The Plan
<div id="Titlecont">
<div id="Picture">
<img src="LogoPicture.png" width=60 height=60>
</div>
<div id="Title">
<h1>Little Hands Daycare</h1>
</div>
<div id="Motto">
<p> "It takes a village to raise a child" </p>
</div>
</div>
<div id="Button">
<a href="Computer SciencesWE.html">
<button type="button">
Home
</button>
</a>
<a href="Timer.html">
<button type="button">
Timer
</button>
</a>
<a href="About Us.html">
<button type="button">
About
</button>
</a>
<a href="Register.html">
<button type="button">
Register
</button>
</a>
<a href="Schedule.html">
<button type="button">
Events
</button>
</a>
<button type="button">
Contact
</button>
</div>
</div>
<!--This is where the daily schedule is coded-->
<br>
<div id="Schedule">
<img src="Calender.jpg" width=800 height=540>
<!--This is where the html displays the output of the js-->
<div id="txtContainer">
<p id="birthdays">
.
</p>
</div>
<div id="BirthdayBorder">
<img src="Birthday Border.jpg" width=800 height=600>
</div>
</div>
</body>
</html>
and the requested portion of the javascript has been added to the top of the old code
You have to stop looping when you find a match. Otherwise, you'll process the non-matching items after it, which overwrites the changes you made.
var birthday_found = false;
for (var i = 0; i < studentProfile.length; i++)
{
//here is where the variables regarding the date were specified and extracted from the object that was converted
bdayMonth = studentProfile[i].birthday.substring(0,2);
bdayDay = studentProfile[i].birthday.substring(3,5);
todayMonth = today.getMonth()+1;
todayDay = today.getDate();
//this is where the comparison part of the code starts, basically the birthday entered by the user is compared with today's date
if ((bdayDay == todayDay) && (bdayMonth == todayMonth))
{
//if the dates are equal to one another then the student's firstname is determined and displayed as an output in the html
document.getElementById("birthdays").innerHTML = studentProfile[i].firstName;
BirthdayBorder.style.opacity = "100";
BirthdayBorder.style.marginTop = "0px";
txtbirthday.style.marginTop = "144px";
birthday_found = true;
break;
}
}
if (!birthday_found)
{
//the program has determined that there are no birthdays today and will display the text instead of a student's name
document.getElementById("birthdays").innerHTML = "No Birthdays Today! ;)";
//this is the styling part for the birthday border to be transparent and moved to a place where it isn't affecting the website's margins and the text is moved to look better than being in empty space
BirthdayBorder.style.opacity = "0";
BirthdayBorder.style.marginTop = "-1000px";
txtbirthday.style.marginTop = "-50px";
}

Categories

Resources