I trying write some strings in file and then read them, but having error message Cannot access a locked file. Tested on iphone and android.
page.xml
<Page xmlns="http://www.nativescript.org/tns.xsd" loaded="pageLoaded" actionBarHidden="true">
<StackLayout>
<Label text="Tap the button" id="label"/>
<Button text="TAP" id="btn" />
</StackLayout>
</Page>
page.js
var frameModule = require("ui/frame");
var view = require("ui/core/view");
var dialogs = require("ui/dialogs");
var fs = require("file-system");
function pageLoaded(args) {
var page = args.object;
var button = view.getViewById(page, "btn");
var label = view.getViewById(page, "label");
button.on("tap", function (){
var documents = fs.knownFolders.documents();
var myFile = documents.getFile("Test_Write.txt");
myFile.writeText("Something")
.then(function () {
myFile.readText()
.then(function (content) {
label.text = content;
}, function (error) {
label.text = error;
});
}, function (error) {
label.text = error;
});
});
}
exports.pageLoaded = pageLoaded;
The write methods lock but never unlock the file.
This has been addressed with the following pull request.
Related
I have a repeater that loads info from SQLite and works well. The user has options to take photos which are stored both in their photo library and in a temp folder. On reloading the page I need to reload the images to for a sliding gallery of thumbnails under the relevant section in the repeater.
The Image repeater is defined as
<Repeater items="{{ images }}" id="{{ repeaterphotoid }}">
<Repeater.itemTemplate>
<Image src="{{localurl}}" width="75" height="75" visibility="{{photoevidence === 'y' ? 'visible' : 'collapse'}}" />
</Repeater.itemTemplate>
</Repeater>
And my code is
exports.takePic = function(args){
var page = args.object;
camera.requestPermissions().then(
function success(){
var livesite = appSettings.getString("livesite");
var images=[];
var whichcamera = args.object;
var options = {saveToGallery: true, keepAspectRation: true, height: 1024 };
var gallery = args.object.page.getViewById("images-"+whichcamera.id);
var source = new imageSourceModule.ImageSource();
camera.takePicture(options).then(function(imageAsset){
var img = new imageModule.Image();
source.fromAsset(imageAsset).then((imageSource) => {
var auditDB = new sqlite("my.db", function(err, db){
if (err){
alert("Failed to open the database", err);
} else {
var tempfilename = livesite+"-"+whichcamera.qid+"-";
db.all("SELECT filename FROM images WHERE filename LIKE '"+tempfilename+"%'").then(rows =>{
//console.log("Images rows="+rows.length+1);
if (rows.length == 0){
imageCount = 1;
}
else
{
imageCount = rows.length+1;
}
var livesite = appSettings.getString("livesite");
// var path = filesystem.path.join(filesystem.knownFolders.documants().path,"photos")
var folder = filesystem.knownFolders.documents();
var filename = livesite+"-"+whichcamera.qid+"-"+imageCount+".jpg";
var imgPath = filesystem.path.join(folder.path,filename);
var saved = imageSource.saveToFile(imgPath,"jpg");
if (saved){
var livesite = appSettings.getString("livesite");
var liveaudit = appSettings.getString("liveaudit");
db.execSQL("INSERT INTO images (localurl,remoteurl,syncd,siteid,filename,question) VALUES(?,?,?,?,?,?)",[imgPath,'-','n',livesite,filename,whichcamera.qid])
var imageList = [];
var tempfilename = livesite+"-"+whichcamera.qid+"-";
var imageSQL = "SELECT localurl,remoteurl,filename FROM images WHERE filename LIKE '"+tempfilename+"%'";
db.all(imageSQL).then(rows =>{
for (var row in rows) {
imageList.push({
localurl: rows[row][0],
filename: rows[row][2]
});
}
const imagesource = fromObject({
images: imageList
});
imagesource.set = ("images", imageList);
var imageholder = args.object.page.getViewById("repeat_"+whichcamera.id);
imageholder.bindingContext = imagesource;
});
};
});
};
});
});
}).catch(function (err) {
alert("Camera Error "+err.message);
})
//alert("Taking Pic with camera "+whichcamera.id);
},
function failure(){
alert("You must allow this app access to the camera and your photos library.")
});
}
Binding to the questions works as expected but I cannot bind the images to the image repeater, nothing happens. Obviously missing something but going code blind.
I am trying to make a simple text clicking game to gain a better understanding of Nativescript.
I first have a label with intro text and a question. Then I have 3 buttons to give an answer to the question.
Once the user clicks one of the buttons I want the first label and the 3 buttons to disappear and the next label to appear.
Here is my code:
This is my home-page.js
var frameModule = require("tns-core-modules/ui/frame");
var HomeViewModel = require("./home-view-model");
var homeViewModel = new HomeViewModel();
exports.loaded = function (args) {
var page = args.object;
page.actionBarHidden = true;
page.bindingContext = homeViewModel;
};
exports.SwordButton = function () {
Display1 = false;
Display2 = true;
console.log("The Sword button was pressed");
};
exports.BowButton = function () {
Display1 = false;
Display2 = true;
console.log("The Bow button was pressed");
};
exports.ShieldButton = function () {
Display1 = false;
Display2 = true;
console.log("The Shield button was pressed");
};
This is my home-page.xml:
<ActionBar title="Home" class="action-bar">
</ActionBar>
<StackLayout class="home-panel">
<Label textWrap="true" text="Text game" class="h2 description-label" />
<Label id="text1" textWrap="true" visibility="{{ Display1 ? 'visible' : 'collapsed' }}"
text="It's a zombie apocalypse! You are looting a store when suddenly a zombie bursts in through the door. You frantically search for a weapon. You find a box containing a sword, a bow and a shield. Which one do you choose?"
class="h2 description-label" />
<Label id="text2" textWrap="true" visibility="{{ Display2 ? 'visible' : 'collapsed' }}" text="You chose poorly." />
<Button text="Sword" tap="SwordButton" />
<Button text="Bow" tap="BowButton" />
<Button text="Shield" tap="ShieldButton" />
</StackLayout>
Here is my home-view-model.js:
var observableModule = require("tns-core-modules/data/observable");
function HomeViewModel() {
var weapon;
var viewModel = observableModule.fromObject({
Display1: true,
Display2: false,
textFieldValue: "",
});
return viewModel;
}
module.exports = HomeViewModel;
I hope I have given enough information for you to help, if not please let me know.
Hope you can help.
I fixed it. Turns out I forgot to set the new value of the Display variables.
This is what my new SwordButton function looks like.
exports.SwordButton = function () {
Display1 = false;
Display2 = true;
console.log("The Sword button was pressed");
homeViewModel.set("Display1", Display1);
homeViewModel.set("Display2", Display2);
};
I did the same thing for the BowButton and the ShieldButton functions.
I can't get the value from my bound textfield. I used the tab template. On the Microsoft Android Emulator. Is there something I need to add to the main tab page view model maybe?
View
<GridLayout class="page-content">
<StackLayout orientation="vertical">
<Label class="page-icon fa" text=""></Label>
<TextField id="txtSearch" text="{{ search }}" hint="Search" keyboardType="email" autocorrect="false" autocapitalizationType="none" />
<Button text="Sign in" tap="searchClick" />
</StackLayout>
</GridLayout>
var SearchViewModel = require("./search-view-model");
var svm = new SearchViewModel();
function onLoaded(args) {
var component = args.object;
component.bindingContext = new SearchViewModel();
}
exports.searchClick = function() {
svm.searches()
.catch(function(error) {
console.log(error);
dialogsModule.alert({
message: "Unfortunately we could not find your account.",
okButtonText: "OK"
});
return Promise.reject();
})
.then(function() {
//frameModule.topmost().navigate("views/list/list");
});
};
exports.onLoaded = onLoaded;
model
For some reason viewModel.get("search") returns nothing. The button fires fine.
const observableModule = require("data/observable");
var fetchModule = require("fetch");
//Info is the returning object
function SearchViewModel(info) {
info = info || {};
var viewModel = new observableModule.fromObject({
search: info.search || ""
});
viewModel.searches = function() {
var test = viewModel.get("search");
return fetchModule.fetch(config.apiUrl + viewModel.get("search"), {
method: "GET",
headers: {
"Content-Type": "application/json"
}
})
.then(handleErrors)
.then(function(response) {
return response.json();
})
.then(function(data) {
config.token = data.Result.access_token;
});
};
return viewModel;
}
You can simply use this.search,
Or you can use this.get("search")
Edit: also on a side note,
In your code behind file, you are creating
var svm = new SearchViewModel();
But you are not assigning svm as the bindingContext, instead you are creating a new instance of SearchViewModel. That might cause some unexpected behavior later.
I have not been able to find a working example of NS+JS for list-picker, non of the examples in the docs have XML examples.
Can anyone help?
What you’ll need to do is bind a <ListPicker>’s items property to an array on your page’s bindingContext. Here’s a basic example:
<!-- main-page.xml -->
<Page xmlns="http://schemas.nativescript.org/tns.xsd" loaded="pageLoaded">
<StackLayout>
<ListPicker
items="{{ pokemon }}"
id="pokemonPicker"
></ListPicker>
</StackLayout>
</Page>
// main-page.js
var Observable = require("data/observable").Observable;
var pageData = new Observable({
pokemon: ["Bulbasaur", "Charmander", "Squirtle"]
});
exports.pageLoaded = function(args) {
var page = args.object;
page.bindingContext = pageData;
page.getViewById("pokemonPicker").addEventListener(
Observable.propertyChangeEvent, function(e) {
if (e.propertyName == "selectedIndex") {
console.log("You selected: " + pageData.pokemon[e.value]);
}
}
);
};
Hi I was wondering if there was a way to preview images before I upload them using angularjs? I am using the this library. https://github.com/danialfarid/angular-file-upload
Thanks. Here is my code:
template.html
<div ng-controller="picUploadCtr">
<form>
<input type="text" ng-model="myModelObj">
<input type="file" ng-file-select="onFileSelect($files)" >
<input type="file" ng-file-select="onFileSelect($files)" multiple>
</form>
</div>
controller.js
.controller('picUploadCtr', function($scope, $http,$location, userSettingsService) {
$scope.onFileSelect = function($files) {
//$files: an array of files selected, each file has name, size, and type.
for (var i = 0; i < $files.length; i++) {
var $file = $files[i];
$http.uploadFile({
url: 'server/upload/url', //upload.php script, node.js route, or servlet uplaod url)
data: {myObj: $scope.myModelObj},
file: $file
}).then(function(data, status, headers, config) {
// file is uploaded successfully
console.log(data);
});
}
}
OdeToCode posted great service for this stuff. So with this simple directive you can easily preview and even see the progress bar:
.directive("ngFileSelect",function(){
return {
link: function($scope,el){
el.bind("change", function(e){
$scope.file = (e.srcElement || e.target).files[0];
$scope.getFile();
});
}
}
It is working in all modern browsers!
Example: http://plnkr.co/edit/y5n16v?p=preview
JavaScript
$scope.setFile = function(element) {
$scope.currentFile = element.files[0];
var reader = new FileReader();
reader.onload = function(event) {
$scope.image_source = event.target.result
$scope.$apply()
}
// when the file is read it triggers the onload event above.
reader.readAsDataURL(element.files[0]);
}
Html
<img ng-src="{{image_source}}">
<input type="file" id="trigger" class="ng-hide" onchange="angular.element(this).scope().setFile(this)" accept="image/*">
This worked for me.
See the Image Upload Widget from the Jasney extension of Bootstrap v3
// start Picture Preview
$scope.imageUpload = function (event) {
var files = event.target.files;
for (var i = 0; i < files.length; i++) {
var file = files[i];
var reader = new FileReader();
reader.onload = $scope.imageIsLoaded;
reader.readAsDataURL(file);
}
}
$scope.imageIsLoaded = function (e) {
$scope.$apply(function () {
$scope.img = e.target.result;
});
}
<input type='file' ng-model-instant onchange="angular.element(this).scope().imageUpload(event)" />
<img class="thumb" ng-src="{{img}}" />