You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Repeater控件中图片占位符的图片绑定失效问题排查

Hey, let's figure out why your Repeater isn't showing those images—there are a few key issues in your code that are causing this:


1. Critical Syntax Error in Observable Setter

You have a broken line where you try to update the observable:

imagesource.set = ("images", imageList);

This is invalid syntax. The set method on an observable (created via fromObject) needs to be called as a function, not assigned. You can either fix it to:

imagesource.set("images", imageList);

Or even simpler, directly assign the property since fromObject makes it observable:

imagesource.images = imageList;

2. Missing photoevidence Field (Images Are Hidden!)

Your Image template uses:

visibility="{{photoevidence === 'y' ? 'visible' : 'collapse'}}"

But when you push items to imageList, you don't include the photoevidence property. Every image is being collapsed automatically! Add this field to each item:

imageList.push({ 
  localurl: rows[row][0], 
  filename: rows[row][2],
  photoevidence: 'y' // 👈 This makes the image visible
});

3. Typo in Camera Options

You wrote keepAspectRation (missing an a) in your camera options—this might cause unexpected behavior with image sizing:

var options = {saveToGallery: true, keepAspectRatio: true, height: 1024 }; // Fixed spelling

4. Redundant Variable Definitions & Async Nesting

You repeat livesite multiple times in nested scopes, and your async code is deeply nested (making it hard to debug). Switching to async/await will clean this up significantly.


Fixed Code Example

Here's your updated takePic function with all the fixes applied:

const camera = require("nativescript-camera");
const imageSourceModule = require("nativescript-image-source");
const filesystem = require("nativescript-file-system");
const appSettings = require("nativescript-app-settings");
const { fromObject } = require("tns-core-modules/data/observable");
const sqlite = require("nativescript-sqlite");

exports.takePic = async function(args){
    try {
        const page = args.object;
        // Request camera permissions first
        await camera.requestPermissions();
        
        const livesite = appSettings.getString("livesite");
        const whichcamera = args.object;
        const options = { saveToGallery: true, keepAspectRatio: true, height: 1024 };
        const source = new imageSourceModule.ImageSource();
        
        // Capture photo
        const imageAsset = await camera.takePicture(options);
        const imageSource = await source.fromAsset(imageAsset);
        
        // Open database connection
        const auditDB = await new sqlite("my.db");
        
        // Calculate next image count
        const tempfilename = `${livesite}-${whichcamera.qid}-`;
        const rows = await auditDB.all(`SELECT filename FROM images WHERE filename LIKE '${tempfilename}%'`);
        const imageCount = rows.length === 0 ? 1 : rows.length + 1;
        
        // Save image to documents folder
        const folder = filesystem.knownFolders.documents();
        const filename = `${livesite}-${whichcamera.qid}-${imageCount}.jpg`;
        const imgPath = filesystem.path.join(folder.path, filename);
        const saved = imageSource.saveToFile(imgPath, "jpg");
        
        if (saved) {
            // Insert record into database
            const liveaudit = appSettings.getString("liveaudit");
            await auditDB.execSQL(
                "INSERT INTO images (localurl,remoteurl,syncd,siteid,filename,question) VALUES(?,?,?,?,?,?)",
                [imgPath, '-', 'n', livesite, filename, whichcamera.qid]
            );
            
            // Fetch updated image list
            const imageRows = await auditDB.all(`SELECT localurl,filename FROM images WHERE filename LIKE '${tempfilename}%'`);
            const imageList = imageRows.map(row => ({
                localurl: row[0],
                filename: row[1],
                photoevidence: 'y'
            }));
            
            // Update Repeater binding
            const imagesource = fromObject({ images: imageList });
            const imageholder = page.getViewById(`repeat_${whichcamera.id}`);
            imageholder.bindingContext = imagesource;
        }
    } catch (err) {
        if (err.message.includes("permission")) {
            alert("You must allow this app access to the camera and your photos library.");
        } else {
            alert(`Error: ${err.message}`);
        }
    }
};

Quick Additional Checks

  • Repeater ID Matching: Ensure the id of your Repeater in XML ({{ repeaterphotoid }}) exactly matches repeat_${whichcamera.id} (e.g., if your button ID is camera1, the Repeater ID should be repeat_camera1).
  • Permissions: Double-check that you've added camera and storage permissions to AndroidManifest.xml (Android) and Info.plist (iOS)—without these, photos won't save or load.

内容的提问来源于stack exchange,提问作者Frank Nicklin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:15:01