Angular 2 Album create - javascript

I want to make an Album creator like on Facebook.
But when I save a picture to the firebase storage and I get back the URL to the picture I put in an object, but the view is not refreshing just if I add a new picture or move the cursor. How can I refresh the view automatically when I get the URL from firebase?
<div class="row pics">
<div class="col-md-4 col-xs-4">
<div class="newItem text-center">
<a (change)="addPicture($event)" class="newAlbum"><input type="file" id="file"/>Add Picture</a>
</div>
</div>
<div class="col-md-4 col-xs-4" *ngFor="let item of newAlbum.pictures; let i = index">
<div class="Item">
<img src="{{item?.pictureS}}" alt="" >
</div>
<textarea class="picture-desc" placeholder="Say something about this photo..." (keyup)="onKey($event,i)">{{item.desc}}</textarea>
</div>
</div>
Backend
readPicture() {
this.picItem = { pictureS: '', pictureF: this.file, desc: '' };
let that = this;
let uploadTask = this.data.albumUpload(this.newAlbum.dirname,this.file.name,this.file);
uploadTask.on('state_changed', function(snapshot) {
var progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
console.log('Upload is ' + progress + '% done');
}, function(error) {
}, function() {
that.picItem.pictureS = uploadTask.snapshot.downloadURL;
console.log(' NEW UPLOAD...');
that.newAlbum.pictures.push(that.picItem);
}
);
}
addPicture(e){
this.file = e.target.files[0];
this.readPicture();
}
onKey(e,i){
this.newAlbum.pictures[i].desc = e.target.value;
}
albumUpload(form: NgForm){
this.newAlbum.title = form.value.album_title;
this.newAlbum.desc = form.value.album_desc;
}

You could use NgZone to to trigger change detection when certain actions are done. You need to inject NgZone into the component. Once thats done you can use , run to update DOM.
constructor( public zone: NgZone){}
that.zone.run(() =>
that.newAlbum.pictures.push(that.picItem);
});
You can read more about ngZone here .
ps: I would advice you to use new arrow funcions to conserve this rather than using that.

Related

How to render an Image loaded from postgres Database in angular

I'm trying to render dinamically and image linked to an Ad in angular, the problem is that even if in tag the 'src' parameter seems to be right it can't show the image.
This is my code in Angular
ngOnChanges(changes: SimpleChanges): void {
console.log("ngOnChanges: " + changes);
console.log(this.ads.length);
for(let i = 0; i< this.ads.length; i++){
this.service.getImage(this.ads[i]).subscribe(blobList => this.ads[i].images = blobList).add( () => {
console.log("Byte: " + this.ads[i].images.at(0));
let div = document.getElementById("ad" + this.ads[i].id) as HTMLDivElement;
console.log(div);
let bytea: ArrayBuffer = this.ads[i].images.at(0) as ArrayBuffer;
const buffer = Buffer.from(bytea);
const blob = new Blob([buffer], {type: 'image/png'});
const image = this.createImageFromBlob(blob);
div.appendChild(image);
});
}
}
This is the function I use to create an HTMLImageElement from a BLOB
public createImageFromBlob(blob: Blob): HTMLImageElement {
const image = new Image();
const url = URL.createObjectURL(blob);
image.src = url;
return image;
}
This is the Ad interface
export interface Ad{
id: number;
title: string;
description: string;
user: User;
property: Property;
price: number;
mq: number;
status: string;
city: string;
images: ArrayBuffer[];
}
This is my code in HTML
<span *ngIf="!isEmpty()">
<span *ngFor="let ad of ads">
<span *ngIf="canShow(ad.status)">
<div class="container justify-content-center">
<div class="card jumbotron">
<div class="text-center badge-info badge" style="margin-top: -2%;" id="statusTitle">
<h2>{{ad.status.toUpperCase()}}</h2>
</div>
<div class="row no-gutters m-3">
<div class="col-lg-5 col-md-7 col-md-12" id="ad{{ad.id}}">
</div>
<div class="col">
<div class="card-block px-2">
<h3 class="card-title">{{ad.title}}</h3>
<p class="card-text">{{ad.description}}</p>
{{ad.price}}
<hr>
{{ad.user.nickname}}
</div>
</div>
</div>
<div class="card-footer w-100 text-muted">
Leggi annuncio
</div>
</div>
</div>
<hr>
</span>
</span>
</span>
I'm adding the java springboot controller that I use to take data from the database. This method returns a List of Byte[] 'cause I have bytea on postgres database.
#GetMapping("/getImage")
public List<byte[]> getImage(HttpServletRequest request, #RequestParam String adId){
List<Image> imageList = DBManager.getInstance().getImageDao().findByAdId(Integer.parseInt(adId));
List<byte[]> imgList = new ArrayList<>();
for (Image image : imageList) {
imgList.add(image.getData());
}
return imgList;
}
And this is the method I use in Angular to call the java server.
getImage(adId: number): Observable<Blob[]> {
return this.http.get<Blob[]>('http://localhost:8080/image', {params: {adId: adId}, responseType: 'json'});
}
As you can see i'm trying to inject the HTMLImageElement in a div linked through an ID.
I tried some other methods but this one is the only that gave me a correct Blob, but on website it only shows the "Image not Found" icon.
image
I can't figure out what I'm doing wrong, any help will be very appreciated, thanks.
I resolved ot converting the byte[] to blob but only adding the base64 to image/jpeg encoding string, thank you all, hope this will help someone.
for(let i = 0; i< this.ads.length; i++){
this.service.getImage(this.ads[i].id).subscribe(blobList => this.ads[i].images = blobList).add( () => {
let image = document.getElementById("img" + this.ads[i].id) as HTMLImageElement;
if(this.ads[i].images.at(0) == null){
image.src = "https://fakeimg.pl/400x250/?text=No%20image"
}else{
image.src = 'data:image/jpeg;base64,' + this.ads[i].images.at(0);
}
});
}

Changing image in child component will update higher most html img tag in parent component

Video
I made a short 15 second Youtube video demonstrating the bug since its rather hard to explain here is video: https://www.youtube.com/watch?v=YXykw2oSh8E --- please ignore my terrible editing skills
Short Summary
I will summarize the error here: If I have two image tags and I am trying to change the image of the lower one that is located lower in the html file, the image on the higher most img tag will be changed as opposed to the one I selected even though the logic is in a seperate component instance
Code layout
In my code I have two <app-image-display> components stacked on top of one another. When I try to update the image of the one with the name of coverPhoto it will update the image in the one named profile. If I move the coverPhoto named instance higher in the html file than profile named instance and try to change profile it will update coverPhoto.
Parent
I have a parent component that looks like this:
....
<div *ngIf="company">
<app-image-display name="profile" id="profile" #profile [image]="company.profileUrl" [uploadPath]='companyProfilePath' (imageUpdated)="updateImage($event, CompanyImage.PROFILE)"></app-image-display>
<app-image-display name="coverPhoto" id="coverPhoto" #coverPhoto [image]="company.coverPhotoUrl" [uploadPath]='companyCoverPath' (imageUpdated)="updateImage($event, CompanyImage.COVER_PHOTO_URL)"></app-image-display>
</div>
.....
You can see it contains two separate instances of the same component called ImageDisplay. One of the instances is designed to handle a profile image and the other a cover photo. I put in temporary logic to show me which on is the cover photo just to be explicit as seen in the video. This component is designed to show the use the previously saved image then allow them to view a new image (tempImage) before saving it to the db. The ImageDisplayComponent looks like the following:
Image Display Html
<img [src]="image" width="200" *ngIf="!tempImage" height="200" class=" img-thumbnail" alt="Responsive
image" onerror="this.src = 'TEMP_IMG_URL_GOES_HERE'">
<img [src]="tempImage" *ngIf="tempImage" width="200" height="200" class=" img-thumbnail"
alt="Responsive image">
<span *ngIf="uploadPath.includes('cover')">Cover Image</span>
<app-image-picker *ngIf="!percentage" (imageSelected)="imageSelected($event) (tempImageSelected)="tempSelected($event)"></app-image-picker>
Image Display TS
And the .ts looks like this:
...
export class ImageDisplayComponent implements OnInit {
#Output() imageUpdated: EventEmitter<string> = new EventEmitter();
#Input() image: string = '';
#Input() uploadPath: string
tempImage: string;
percentage: Observable<number>;
selectedPictureFile: File;
task: AngularFireUploadTask;
constructor(
private dbs: AngularFireStorage,
private toastService: ToastService
) { }
ngOnInit(): void {
console.log(this.uploadPath)
}
imageSelected(image: File) {
this.selectedPictureFile = image;
this.fileUpload(this.uploadPath, this.selectedPictureFile);
}
async fileUpload(path: string, file: File): Promise<void> {
const ref = this.dbs.ref(path);
this.task = this.dbs.upload(path, file);
this.percentage = this.task.percentageChanges();
let imageUrl = '';
from(this.task).pipe(
switchMap(() => ref.getDownloadURL()),
map((img) => imageUrl = img),
finalize(() => delete this.percentage)
).subscribe(() => {
this.imageUpdated.emit(imageUrl)
},(error) => {
this.toastService.show(`${error.message}`, {
delay: 3000,
autohide: true
});
});
}
tempSelected(imageUrl: string) {
this.tempImage = imageUrl;
}
}
...
ImagePickerComponent Html
app-image-picker looks like the following:
<div style="margin: 5px">
<label for="file-upload" class="custom-file-upload">
{{labelText}}
</label>
<input type="file" id="file-upload" (change)="onPictureSelected($event)" accept=".png, .jpg">
<div class="row">
<button *ngIf="pictureSelected" class="btn btn-info m-1" [disabled]="!pictureSelected" (click)="uploadPicture()">
Save
</button>
<button *ngIf="pictureSelected" class="btn btn-warn m-1" [disabled]="!pictureSelected" (click)="cancel()">
Cancel
</button>
</div>
ImagePickerComponent TS
This is what the onPictureSelected function looks like:
// image selection and verification.
onPictureSelected(event) {
this.selectedPictureFile = event.target.files[0] as File;
const reader = new FileReader();
reader.readAsDataURL(this.selectedPictureFile);
if (!this.imageService.isImage(this.selectedPictureFile.name)) {
this.pictureSelected = false;
} else if (!this.imageService.isAllowedSize(this.selectedPictureFile.size)) {
this.pictureSelected = false;
} else {
// tslint:disable-next-line:no-shadowed-variable
reader.onloadend = (event: any) => {
if (event.target) {
this.selectedPictureURL = event.target.result;
this.tempImageSelected.emit(this.selectedPictureURL);
}
};
this.pictureSelected = true;
}
}
I am on Angular version 9.0.3

PubNub ChatEngine "Converting circular structure to JSON" error after joining back to 1-1 chat using Angular

I'm trying to wrap my head around this PubNub ChatEngine example using Angular for first time https://github.com/pubnub/chat-engine-examples/tree/master/angular/simple
In demo when you click on user from the list new channel with random name is generated and user invited to it. So if you leave chat click on user again you connect to new channel.
I'm trying to do 1-1 chat rooms, that you could leave than join back, so changed channel name to be clicked user uuid. Now if I leave the channel, join back to it and try to send message it's not being shown in list, though it's being sent and user you are chatting with receives it.
In console I'm getting "Uncaught (in promise) TypeError: Converting circular structure to JSON" when starting to type (as have chat engine typing indicator running) and after submit.
I guess that's something to do with removing chat from global scope using splice() method and after joining back new chat being added. It works in demo because there are getting new channel each time and removing it, but not if using same channel now.
I tried to use splice() instead to see what happens. If I close chat and join back to it, it stays in DOM, and new one is added to scope, so have two same chat elements in DOM. If I type and send message on second one, it's not being displayed at it, but instead on first one that tried to close.
How could I get this working properly, can splice() be used in my case and I'm missing something else that is causing the error?
$scope.leave = (index) => {
$scope.chat.leave();
$scope.chats.splice(index, 1);
//$scope.chats.slice(index, 1);
//$scope.chats.splice( $scope.chats.indexOf($scope.chat), 1 );
}
angular.module('chatApp', ['open-chat-framework'])
.run(['$rootScope', 'ngChatEngine', function($rootScope, ngChatEngine) {
$rootScope.ChatEngine = ChatEngineCore.create({
publishKey: 'pub-c-d8599c43-cecf-42ba-a72f-aa3b24653c2b',
subscribeKey: 'sub-c-6c6c021c-c4e2-11e7-9628-f616d8b03518'
}, {
debug: true,
globalChannel: 'chat-engine-angular-simple'
});
// bind open chat framework angular plugin
ngChatEngine.bind($rootScope.ChatEngine);
// set a global array of chatrooms
$rootScope.chats = [];
}])
.controller('Chat', function($scope) {
$scope.chat.plugin(ChatEngineCore.plugin['chat-engine-typing-indicator']({
timeout: 5000
}));
// every chat has a list of messages
$scope.messages = [];
// we store the id of the lastSender
$scope.lastSender = null;
// leave a chatroom and remove from global chat list
$scope.leave = (index) => {
$scope.chat.leave();
$scope.chats.splice(index, 1);
}
// send a message using the messageDraft input
$scope.sendMessage = () => {
$scope.chat.emit('message', {
text: $scope.messageDraft
});
$scope.messageDraft = '';
}
// when we get notified of a user typing
$scope.chat.on('$typingIndicator.startTyping', (event) => {
event.sender.isTyping = true;
});
// when we get notified a user stops typing
$scope.chat.on('$typingIndicator.stopTyping', (event) => {
event.sender.isTyping = false;
});
// function to add a message to messages array
let addMessage = (payload, isHistory) => {
// if this message was from a history call
payload.isHistory = isHistory;
// if the last message was sent from the same user
payload.sameUser = $scope.messages.length > 0 && payload.sender.uuid == $scope.messages[$scope.messages.length - 1].sender.uuid;
// if this message was sent by this client
payload.isSelf = payload.sender.uuid == $scope.me.uuid;
// add the message to the array
$scope.messages.push(payload);
}
// if this chat receives a message that's not from this sessions
$scope.chat.search({
event: 'message'
}).on('message', function(payload) {
// render it in the DOM with a special class
addMessage(payload, true);
})
// when this chat gets a message
$scope.chat.on('message', function(payload) {
// render it in the DOM
addMessage(payload, false);
});
})
.controller('OnlineUser', function($scope) {
// create a new chat
$scope.newChat = function(user) {
// define a channel
let chan = user.uuid;
// create a new chat with that channel
let newChat = new $scope.ChatEngine.Chat(chan);
// we need to auth ourselves before we can invite others
newChat.on('$.connected', () => {
// this fires a private invite to the user
newChat.invite(user);
// add the chat to the list
$scope.chats.push(newChat);
});
};
})
.controller('ChatAppController', function($scope) {
// create a user for myself and store as ```me```
$scope.ChatEngine.connect(new Date().getTime(), {}, 'auth-key');
$scope.ChatEngine.on('$.ready', (data) => {
$scope.me = data.me;
$scope.me.plugin(ChatEngineCore.plugin['chat-engine-random-username']($scope.ChatEngine.global));
$scope.ChatEngine.global.plugin(ChatEngineCore.plugin['chat-engine-online-user-search']());
// when I get a private invit
$scope.me.direct.on('$.invite', (payload) => {
let chat = new $scope.ChatEngine.Chat(payload.data.channel);
chat.onAny((a,b) => {
console.log(a)
});
// create a new chat and render it in DOM
$scope.chats.push(chat);
});
// bind chat to updates
$scope.chat = $scope.ChatEngine.global;
// hide / show usernames based on input
$scope.userSearch = {
input: '',
fire: () => {
// get a list of our matching users
let found = $scope.ChatEngine.global.onlineUserSearch.search($scope.userSearch.input);
// hide every user
for(let uuid in $scope.chat.users) {
$scope.chat.users[uuid].hideWhileSearch = true;
}
// show all found users
for(let i in found) {
$scope.chat.users[found[i].uuid].hideWhileSearch = false;
}
}
};
$scope.userAdd = {
input: '',
users: $scope.userAdd,
fire: () => {
if($scope.userAdd.input.length) {
$scope.userAdd.users = $scope.ChatEngine.global.onlineUserSearch.search($scope.userAdd.input);
} else {
$scope.userAdd.users = [];
}
}
};
});
});
<div class="container-fluid" ng-controller="ChatAppController">
<div class="row">
<div class="col-md-6">
<div class="card">
<div class="card-block">
<h4 class="card-title">ChatEngine</h4>
<p class="card-text">Your are {{me.state.username}} with uuid {{me.uuid}}</p>
</div>
<ul id="online-list" class="list-group list-group-flush">
<li class="list-group-item" ng-repeat="(uuid, user) in chat.users" ng-hide="user.hideWhileSearch" ng-controller="OnlineUser">
{{user.state.username}}
<span class="show-typing" ng-show="user.isTyping">is typing...</span>
</li>
</ul>
<div class="card-block">
<form class="send-message" ng-submit="userSearch.fire()">
<div class="input-group">
<input id="usernameSearch" type="text" class="form-control message" placeholder="Search for Username" ng-change="userSearch.fire()" ng-model="userSearch.input">
<span class="input-group-btn">
<button class="btn btn-primary" type="submit">Search</button>
</span>
</div>
</form>
</div>
</div>
</div>
<div class="col-md-6">
<div id="chats" class="row" ng-repeat="chat in chats" ng-controller="Chat">
<div class="chat col-xs-12">
<div class="card">
<div class="card-header">
<div class="col-sm-6">
{{chat.channel}}
</div>
<div class="col-sm-6 text-right">
x
</div>
</div>
<ul class="list-group list-group-flush online-list-sub">
<li class="list-group-item" ng-repeat="(uuid, user) in chat.users" ng-hide="user.hideWhileSearch" ng-controller="OnlineUser">
{{user.state.username}}
<span class="show-typing" ng-show="user.isTyping">is typing...</span>
</li>
</ul>
<div class="card-block">
<div class="log">
<div ng-repeat="message in messages" ng-class="{'hide-username': message.sameUser, 'text-muted': message.isHistory, 'text-xs-right': !message.isSelf}">
<p class="text-muted username">{{message.sender.state.username}}</p>
<p>{{message.data.text}}</p>
</div>
</div>
<p class="typing text-muted"></p>
<form class="send-message" ng-submit="sendMessage(chat)">
<div class="input-group">
<input ng-model="messageDraft" ng-change="chat.typingIndicator.startTyping()" type="text" class="form-control message" placeholder="Your Message...">
<span class="input-group-btn">
<button class="btn btn-primary" type="submit">Send</button>
</span>
</div>
</form>
</div>
<hr />
<div class="card-block">
<h6>Add a user to this chat</h6>
<fom ng-submit="userAdd.fire()">
<div class="input-group">
<input id="usernameSearch" type="text" class="form-control message" placeholder="Add User" ng-change="userAdd.fire()" ng-model="userAdd.input">
</div>
</form>
<ul class="list-group list-group-flush online-list-sub">
<li class="list-group-item" ng-repeat="(uuid, user) in userAdd.users" ng-controller="OnlineUser">
{{user.state.username}}
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
Issue is resolved by upgrading to the latest ChatEngine version. As per the ChatEngine github repo issue:
it's working correctly with chat-engine#0.9.5, I was using chat-engine#0.8.4

Load more data using vue js when page is bottom area

I tried to make my Load More data when my page scroll to the bottom. The first thing is I make a div element that I put at the end of the data loop.
<div class="products">
<p>{{ status }}</p>
<div class="product" v-for="(item, index) in items">
<div>
<div class="product-image"><img :src="item.link" alt=""></div>
</div>
<div>
<h4 class="product-title">{{ item.title }}</h4>
<p>Price : {{ price }}</p>
<button class="add-to-cart btn" #click="addItem(index)">Add Item To Cart</button>
</div>
</div>
<div id="product-list-bottom"></div>
</div>
Div element with id product-list-bottom I will detect it using scrollMonitor.js
My default data :
data: {
status: 'Empty product',
total: 0,
items: [],
cart: [],
newSearch: 'anime',
lastSearch: '',
price: STATIC_PRICE,
result: []
}
Inside mounted I detected scroll to bottom :
mounted: function() {
this.onSubmit()
var vueInstance = this
var elem = document.getElementById('product-list-bottom')
var watcher = scrollMonitor.create(elem)
watcher.enterViewport(function() {
vueInstance.appendItems()
})
}
Inside mounted I call onSubmit :
onSubmit: function() {
this.items = ''
this.status = "Searching keyword '" + this.newSearch + "' on server ..."
this.$http.get('/search/'.concat(this.newSearch))
.then(function(response) {
this.lastSearch = this.newSearch,
this.status = 'Find ' + response.data.length + ' data'
this.result = response.data
this.appendItems()
})
}
And inside onSubmit I call appendItems function :
appendItems: function() {
if(this.items.length < this.result.length) {
var start = this.items.length
var end = parseInt(this.items.length + 5)
var append = this.result.slice(start, end)
this.items = this.items.concat(append)
console.log(append)
}
}
All goes well, but when I scroll down I get an error message :
This is because this line :
this.items = this.items.concat(append)
How do I make the data on xxx change (always added five new data from the array) according to the command on the line :
var end = parseInt(this.items.length + 5)
Thanks
it seems '/search/'.concat(this.newSearch) gets evaluated into function and not an actual string value
Try this if you are using babel/webpack
this.$http.get(`/search/`${this.newSearch}`)
Or if not
this.$http.get('/search/' + this.newSearch)
I think since Vue 2.3+ or so you can get this done without any jQuery stuff or any other dependencies:
<style>
.scrollbar{
overflow-y: scroll;
//...
}
.styled-scrollbar::-webkit-scrollbar
.styled-scrollbar::-webkit-scrollbar-thumb
.styled-scrollbar::-webkit-scrollbar-track{
//styling
}
</style>
<template>
//...
<div #scroll="scroll" class="scrollbar">
<div v-for="item in items" :key="item.id">
//TODO: item content
</div
</div>
//...
</template>
<script>
{
data: {
//..
lastScrollUpdate:0
}
//..
mounted: {
scroll:function (e) {
var scrollBar=e.target;
if((scrollBar.scrollTop + scrollBar.clientHeight >= scrollBar.scrollHeight-20)){
var t=new Date().getTime();
if((t-this.lastScrollUpdate)>3000){
this.lastScrollUpdate=t;
console.log('reached end: '+scrollBar.scrollTop+' '+scrollBar.clientHeight+' '+scrollBar.scrollHeight);
//TODO: load more data
}else{
console.log("< 3sec between scoll. no update");
}
}
},
//..
}
}
</script>
You may also want to adjust this to "#scroll.passive", in order to let the scroll-function be executed parallel to the UI (https://v2.vuejs.org/v2/guide/events.html#Event-Modifiers)

Scope variable is also updating non scope variable on change

I'm writing a user settings page in Angular that will be used to update the users profile settings. This is how I've done it (pardon my use of jquery please)
$scope.userObj = {};
var userObjTemp = {};
$http.get('/api/to/get/user').success(function(data) {
if (data.success != true) {
$state.go('index');
} else {
$scope.userObj.user = data.response; //scope variable to show in html form
userObjTemp.user = data.response; //temp data in case someone cancels editing
var tempDob = $scope.userObj.user.dob;
$scope.userObj.user.dob = tempDob.split('-')[2] + '/' + tempDob.split('-')[1] + '/' + tempDob.split('-')[0];
console.log({
userObjData: $scope.userObj
});
console.log({
tempData: userObjTemp
});
}
});
$scope.showSetting = function(target) {
$('.setting-edit-row').hide();
$('.jr-input-setting').show();
$('#' + target + '-input').hide();
$('#' + target).show();
}
$scope.saveSetting = function(key) {
var postDict = {};
postDict[key] = $scope.userObj.user[key];
$http.put('/api/user', postDict).success(function(data) {
$scope.userObj.user = data.response;
$('.setting-edit-row').hide();
$('.jr-input-setting').show();
})
}
$scope.shutSetting = function(target) {
$scope.userObj.user = {};
$scope.userObj.user = userObjTemp.user;
$('#' + target).hide();
$('#' + target + '-input').show();
}
My HTML is as follows:
<div class="row setting-fixed-row">
<div class="col-lg-2">
<div class="setting-label">
Name
</div>
</div>
<div class="col-lg-8">
<input class="jr-input-setting" id="setting-name-input" disabled="true" ng-model="userObj.user.display_name" type="text" placeholder="Display Name">
</div>
<div class="col-lg-2">
<div class="edit-btn" ng-click="showSetting('setting-name')">
Edit
</div>
</div>
<div class="col-lg-12 setting-edit-row" id="setting-name">
<div class="row">
<div class="col-lg-12">
<span class="glyphicon glyphicon-remove shut-det" style="margin-bottom: 5px;" ng-click="shutSetting('setting-name')"></span>
</div>
<div class="col-lg-offset-2 col-lg-8">
<input class="jr-input-edit" ng-model="userObj.user.display_name" placeholder="Display Name" id="display_name" ng-change="showVal()">
</div>
<div class="col-lg-2">
<div class="save-settings" ng-click="saveSetting('display_name')">
Save
</div>
</div>
</div>
</div>
</div>
The idea behind shutSetting() is to shut the editing panel setting-edit-row and restore the original data that I got from the api. However, when I do this, it shows me the temp variable being the same as the $scope.userObj variable. I added a $scope.showVal function to show the variables on change of the input form:
$scope.showVal = function(){
console.log({userObj: $scope.userObj});
console.log({temp: userObjTemp});
}
For some reason, both variables are getting updated. How do I fix this as I've never faced something similar before.
The problem is that you are referencing objects instead of copying them. Thus
$scope.userObj.user = data.response;
userObjTemp.user = data.response;
points all to the same object. Then, when you update one of the two also the other gets updated.
userObjTemp.user = angular.copy(data.response)
this makes a copy.
Just in case: https://jsfiddle.net/qzj0w2Lb/
The problem is, that both of your variables are referencing the same object data.response. Depending on the object, you could use $.extend(true, {}, data.response); to get a clone of the object.
Be aware though, that this is not a true "deep copy" when custom objects are involved!

Categories