#javascript #arrays #json #firebase #google-cloud-firestore
#javascript #массивы #json #firebase #google-cloud-firestore
Вопрос:
В настоящее время я пытаюсь составить анкету, в которой пользователи оценивают изображение. Я хочу передать значение, которое пользователь оценил изображению, наряду с изображением, которое они оценили, в базу данных. В настоящее время я печатаю это в журнале консоли, но у меня возникли проблемы с отправкой его в базу данных. В нем говорится, что данные переключателя не являются объектом. Я впервые использую firebase и имею небольшой опыт работы с JS.
function validate() {
var radio = document.getElementsByName("answer");
var checked = false;
for (var i = 0; i < radio.length; i ) {
if (radio[i].checked) {
checked = true;
break;
} else {
checked = false;
}
}
if (checked) {
for (var i = 0; i < radio.length; i )
{
if (radio[i].checked)
{
selected = (radio[i].value)
window.sessionStorage.setItem("selected", JSON.stringify(selected));
console.log(selected)
changeImage();
}
}
} else {
alert("You must select an answer!")
}
}
var currentImage = 0;
var imageArray = ["/Users/rate/images/images/practice/sun1.jpg", "/Users/rate/images/images/practice/sun2.jpg", "/Users/rate/images/images/practice/sun3.jpg", "/Users/rate/images/images/practice/sun4.jpg"]
function changeImage(){
if (currentImage >= imageArray.length - 1) {
writeToDB();
} else {
currentImage = 1;
}
document.getElementById("mainImage").src = imageArray[currentImage]
img = imageArray[currentImage].slice(-8)
console.log(img)
window.sessionStorage.setItem("selected", JSON.stringify(img));
}
function writeToDB() {
var selected = JSON.parse(window.sessionStorage.getItem("selected"));
var firebaseConfig = {
apiKey: "***",
authDomain: "**",
databaseURL: "**",
projectId: "**",
storageBucket: "**",
messagingSenderId: "**",
appId: "**",
measurementId: "**"
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
var db = firebase.firestore();
db.collection("selected").doc().set(selected)
.then(function () {
console.log("Document successfully written!");
})
.catch(function (error) {
console.error("Error writing document: ", error);
});
}
<!DOCTYPE html>
<html>
<head>
<title> App Icons </title>
<link rel="stylesheet" type="text/css" href="/Users/rate/css/mainstyle.css">
<script type="text/javascript" src="/Users/rate/js/main.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.0.0/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.0.0/firebase-analytics.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.0.0/firebase-auth.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.0.0/firebase-database.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.0.0/firebase-firestore.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.0.0/firebase-storage.js"></script>
</head>
<body class="body">
<div>
<div>
<hr>
<div class=topbar>
<h1> Do you find this App Icon aesthically pleasing</h1>
</div>
<hr>
<div class=image>
<img src="/Users/rate/images/images/practice/sun1.jpg" id="mainImage"/>
</div>
<hr>
<div class=answer>
<div id=answer>
<label> Strongly Agree </label>
<label><input type="radio" name="answer" value="1" required><span>1</span></label>
<label><input type="radio" name="answer" value="2" required><span>2</span></label>
<label><input type="radio" name="answer" value="3" required><span>3</span></label>
<label><input type="radio" name="answer" value="4" required><span>4</span></label>
<label><input type="radio" name="answer" value="5" required><span>5</span></label>
<label> Strongly disagree</label>
<hr>
</div>
</div>
<div class=complete>
<input type="button" onclick="validate()" value="I am complete">
</div>
</body>
Комментарии:
1. Вы пытаетесь записать строку src изображения в базу данных без указания какого-либо ключа. На самом деле вы не пытаетесь обновить коллекцию фактическим документом. В вашем конкретном случае может иметь смысл иметь документ с вызываемым ключом
images
, возможно, и чтобы этот ключ содержал истинный массив. Затем при обновлении вы считываете массив и[...arr, selected]
добавляете его в этот массив.2. да, я рад записать строку src изображения в базу данных, чтобы я мог определить скорость для этого изображения! как мне сделать то, что вы предлагаете?
Ответ №1:
Таким образом, ответ немного сложнее, учитывая, что вы хотите иметь больше данных, чем вы на самом деле сообщаете базе данных. Структура данных для каждого документа может быть примерно такой:
{
url: /* string containing image's url */,
rating: [4, 2, 5, 0] /* array containing ratings given for this image
}
И каждое изображение должно быть представлено практически одинаково — поэтому, если у вас была вызвана коллекция images
, у вас может быть что-то вроде этого:
const dbRef = firebase.firestore();
const imagesRef = dbRef.collection('images');
const oneImage = imagesRef.doc('JdBPHMYWfNMMlMpfsjv5');
oneImage.get().then(function(doc){
console.log( doc.data() )
// that might return
{
'url': '/img/sun002.jpg',
'rating': [5,2,3,2,0,5]
}
/***
* but! In your case, you'd likely want to create the HTML fragment
* you'll be injecting for this particular image:
***/
// so let's pull all the stuff out of the database, and create an object
// that includes the image's id.
const image = {id: doc.id, ...doc.data() }
// Using that, we can create an HTML fragment that generates the radio buttons
const imageEl = document.createRange().createContextualFragment(`<div class='img-container'>
<img src='${image.url}'>
<fieldset class='image-rating'>Rate this image:
<label>0 <input type='radio' name='rating' data-uid='${image.id}' value=0 /></label>
<label>1 <input type='radio' name='rating' data-uid='${image.id}' value=1 /></label>
<label>2 <input type='radio' name='rating' data-uid='${image.id}' value=2 /></label>
<label>3 <input type='radio' name='rating' data-uid='${image.id}' value=3 /></label>
<label>4 <input type='radio' name='rating' data-uid='${image.id}' value=4 /></label>
<label>5 <input type='radio' name='rating' data-uid='${image.id}' value=5 /></label>
</fieldset>
</div>
'`)
// Let's add a listener for the click on the wrapper for all these radios
imageEl.querySelector('.image-rating').addEventListener('click', handleRatingClick)
// And finally, let's add this image block to the page!
document.querySelector("#images-content-pane").appendChild(imageEl)
})
Обратите внимание, что каждое изображение является отдельным doc
в коллекции, но оно может содержать любые свойства, которые вам могут понравиться. Вы можете добавить caption
свойство или что-то еще, что может быть вам полезно.
Но есть несколько вещей, на которые следует обратить внимание:
- Я программно создаю контейнер каждого изображения и динамически добавляю прослушиватель к каждому набору полей.
- Я добавляю
data-uid
атрибут к каждой радиокнопке. Это понадобится нам позже, чтобы мы знали, какой документ с изображением мы обновляем!
Затем, позже, когда вы добавляете рейтинг для этого изображения, вы просто ссылаетесь на это конкретное изображение и добавляете выбранный рейтинг в массив:
// In my case, I had a fieldset wrap all my radio buttons, and a click was handled there:
const handleRatingClick = (event) =>{
// First, let's get the clicked el:
const ratingBtn = event.target;
const imageId = ratingBtn.dataset.uid;
const rating = ratingBtn.value;
// And here I update the array in the rating property, by adding the given value
imagesRef.doc(imageId).update({
rating: firebase.firestore.FieldValue.arrayUnion(Number(rating))
})
}
Обратите внимание, что это не единственный и даже не правильный способ. Дело в том, что вам нужно рассматривать каждое изображение как документ в базе данных, и вам нужно предоставить firestore объект при его создании или обновлении.
Вы могли бы поступить так, как вы делаете, и работать с изображением в localStorage / sessionStorage, но даже тогда значение в sessionStorage должно быть объектом, содержащим
{
url,
answer
}
И выполнение .set()
этого будет просто перезаписывать значение answer каждый раз, а не сохранять их с течением времени. Кроме того, для вашей работы вам необходимо сохранить doc.id где-нибудь.
Это очень многословный способ сказать: «Да, это очень выполнимо, но это чертовски сложная тема». У меня есть копия этой работы: https://repl.it/@TobiasParent/Firestore-image-doc
Комментарии:
1. спасибо вам за все это! в итоге я решил проблему, сохранив имя изображения и номинальное значение в словаре и передал его в firebase
Ответ №2:
Решаемая путем добавления имени изображения и номинального значения в словарь