I am using stackView and with a button press I chance the page by using push and pop. I want to save same variable value and when I open the page again, I want to keep continue using that variable with its value when page is closed.That is why I declared the variables in the main qml :
Window{
id:main
property var isSomethingOn:false
StackView{
id:contentFrame
initialItem:Qt.resolvedUrl("qrc:/MainPage.qml")
Connections{
target:contentFrame.currentItem
onBackButtonPressed:{
contentFrame.pop()
}}}}}
and in the other page I use that variable like:
Item{
id:Page1
signal backButtonPressed()
Image{
id:button1
MultiPointTouchArea{
main.isSomethingOn = !main.isSomethingOn
if(main.isSomethingOn){
button2.buttonImageColor="Imgs/button_left_red.png"
}
else{
button2.buttonImageColor="Imgs/button_left_blue.png"
}
}
}
Now I expect isSomethignOn to be saved and not to be deleted between page transitions. But it indeed get deleted. How can I solve that issue?
The value is getting saved, but you probably can't tell because bindings don't automatically work with var properties. var properties do not automatically notify when their value changes. You can manually trigger them by calling isSomethingOnChanged(), but there's no reason to do that unless you actually need your property to be a var. In your case changing it to a bool should be all you need to do.
For your additional question about push and pop, see the docs. Particularly this line:
This means that any item pushed onto a StackView will never be
destroyed by the StackView; only items that StackView creates from
Components or URLs are destroyed by the StackView.
Related
This is my first question in Stack Overflow. I'll try to be specific but I don't know how to keep this short, so this is going to be a long post. Sorry about that. I promise I searched and tried a lot of stuff before asking, but I'm kind of lost now.
I'm developing a simple app in Angular 6 to keep track of software requisites and the tests associated to those requisites.
I have a component, called RequisiteList, whose HTML part consists in a mat-table with an Array of my own Requisite model class as [dataSource]. This array is received as an #Input parameter, and it also has an #Output parameter which is an EventEmitter that notifies and passes to the parent component every time a Requisite on the list is clicked.
I make use of RequisiteList inside of ReqListMain, which is a component consisting on the list and a hierarchical tree for filtering. This component is working fine, showing, and filtering requisites as intended. This component also captures the #Output event of the list and passes it as an #Output to its parent.
Finally (for what it's related to this question), I have a TestView component that has both an instance of RequisiteList to show the requisites currently associated to current test, and an instance of ReqListMain to add new requisites to current test (like a "browser"). This TestView has an instance of the model class Pectest corresponding to the test that is being currently visualized, which has an array of Requisite.
The idea in this last component was that whenever a requisite of the "browser" list was clicked, it was added to the current test's list. In order to do that, in the callback method associated to the #Output event of the browser list, I tried to add the Requisite received as a parameter:
addrequisite(requisite: Requisite) {
this.currentTest.requisites.push(requisite);
console.log('Current test: ');
console.log(this.currentTest);
}
In the HTML part of TestView, I inserted the RequisiteList component like this:
<app-requisitelist [requisites]="currentTest.requisites" ngModel name="reqlistview"></app-requisitelist>
(The ngModel property is part of the things I've been trying, I'm not sure it's necessary).
The result is:
The clicked requisite is not shown in the list.
In the console output I can see the content of currentTest object, and I verify that clicked requisites are in fact added to the requisites array of that object, so the event fires and the object is passed upwards by the children components.
I'm not sure if my problem is that data binding is made by value (I don't think so, as I bind an Array, which is an object AFAIK), or the table is not detecting data changes (I've tried to force data change detection with ChangeDetector), or anything else.
You pass a array to the app-requisitelist component. This component waits this array changes to update the content. When you do this.currentTest.requisites.push(requisite), the array this.currentTest.requisites doesn't change, I mean, if you do
const tmp = this.currentTest.requisites;
this.currentTest.requisites.push(requisite)
if (tmp === this.currentTest.requisites) {
console.log('The arrays are the same');
}
You will get the log printed. So, I suggest do something like that:
addrequisite(requisite: Requisite) {
this.currentTest.requisites.push(requisite);
this.currentTest.requisites = this.currentTest.requisites.map(item => item);
console.log('Current test: ');
console.log(this.currentTest);
}
The inserted line forces this.currentTest.requisites to be a new array with the same content.
I have an AngularJS application that manages badges. In the application is a form to set the badge # and the name of the person it is assigned to, etc. This gets stored in $scope.badge.
When the user submits the form, I want to add the new badge to a list of badges, which is displayed below the form.
Partial code looks like this:
var badge = angular.copy($scope.badge); // make a copy so we don't keep adding the same object
$scope.badgeList.push(badge);
The first time I run this code, it adds the badge as expected.
Any subsequent time I run this code, the next badge REPLACES the previous badge in the badgeList. In other words, if I add 5 badges, the badgeList still only has 1 object in it because it just keeps getting replaced.
I'm thinking that this may be happening because the same object keeps getting added? Maybe I'm wrong? I am using angular.copy to try and avoid that happening, but it doesn't seem to be working.
Any thoughts on this?
$scope.badgeList.push(($scope.badge);
console.log($scope.badgeList)
no need to use angular.copy since you are ultimately storing all the badges in an array
angular.copy is used when you want to make a clone of object and not update the existing object and the clone's change are not reflected in main object.
If you just want to maintain a list of badges you can execute this block of code
like this
function addBadges(){
$scope.badgeList.push(($scope.badge);
console.log($scope.badgeList)
}
If you are refreshing the controller then obviously the variable will be reset and for such a case you need to make use of angular services.
Create a service and inside the service you need to define getter and setter method that will help in data persistence
and your bages array if saved in service will persist till the application is in foreground.
You could do something like this.
function addBadges(){
//initialize if undefined or null
if(!$scope.badgeList){
$scope.badgeList = [];
}
//Check if badge does not exists in the list
if ($scope.badgeList.indexOf($scope.badge) === -1) {
//Add to badge list
$scope.badgeList.push($scope.badge);
}
}
On my SharePoint there is a website where a single list-item is loaded based on a user's selection with JavaScript and CSOM. This list item has a total of ~60 properties defined in it's list definition.
In HTML input fields the user can modify most of the properties after jQuery filled in the loaded properties to their corresponding input fields. When the "save" button is pressed, the properties are collected from the inputs via jQuery and put into a simple JS-object (itemProps):
var itemprops = {
'foo': $('#foo-input').val(),
'bar': $('#bar-input').val()
}
Then, the following function gets called:
function updateListItem(itemProps, onItemAdded, onItemError) {
var list = web.get_lists().getByTitle('ListTitle');
var listItem = list.getItemById(id);
for (var propName in itemProps) {
if (itemProps.hasOwnProperty(propName)) {
listItem.set_item(propName, itemProps[propName]);
}
}
listItem.update();
context.executeQueryAsync(
function() {
onItemAdded(listItem);
},
onItemError
);
}
Debugging shows me, that the data in itemProps are valid. But sometimes (I can't reproduce that effect deterministically) some properties get lost and when I look at the list item in the list on the SharePoint some of the properties are empty, as if itemProps had null or "" associated to that property. When I first tried to debug this I simply created an item and saved it (correctly, with all properties) and then loaded and saved it again without modification but some properties got lost.
Other properties get updated correctly and sometimes this doesn't happen at all.
Is there any way to make sure this effect does't occur or at least to detect it and retry updating the data, before the user's inputs get lost?
I notice you're not invoking context.load(listItem) before calling context.executeQueryAsync() which might cause issues with the listItem object's values being stale or dehydrated.
The code in your question looks like it should still be setting the specified values correctly on the list item, although there may be some code later on (such as in the onItemAdded function) that's running into false assumptions or subtle data differences from the inadequately loaded list item.
I have a page with an ion-navbar, when I navigate to the next page I use the following:
this.nav.push(SubCategoryPage, {
employeeModel: this.employeeModel
});
It passes the param parameter successfully to the next page.
When I am in the next page (SubCategoryPage), I update the parameter object (employeeModel). My question is, when I click the back arrow to return to the previous page, how do I pass the modified parameter object (employeeModel) back?
When back is clicked, the ngOnDestroy is called, do I use this, but then how do I pass the parameter object?
OR, is there some other scope I should put the object in? (How do you pass objects from one page to another, including back?) What's best practice?
Thanks
I recommending caching the object in a provider. That way, its properties will remain the same when navigating between your components. By caching, all I mean its a simple get and setter.
SOLVED:
in app.ts I need to set the object, then it is shared between pages
ionicBootstrap(MyApp, [EmployeeModel]);
ref: https://www.joshmorony.com/an-in-depth-explanation-of-providers-in-ionic-2/
I have a controller where I get some data to be updated on my page, but I'm having some kind of issue with the data that is injected in my controller.
Basically the data that is injected in my controller keeps updated always in real time, but I need the first data loaded in the page be saved in a variable and not be changed, but for some reason it keeps being updated.
My code:
vm.storedData = null;
function activate() {
if(vm.storedData == null){
vm.storedData = data.condition_lines;
}
}
activate();
Am I doing something wrong?
I believe this is caused by the way Javascript stores objects.
data is an object. data doesn't store condition_lines, it stores a reference to condition_lines, so setting vm.storedData = data.condition_lines;, causes assignment by reference. As a result, vm.storedData will ALWAYS equal data.condition_lines.
You could use angular.copy() to effectively assign by value instead (it does more complex stuff under the hood, but the results are the same).
vm.storedData = angular.copy(data.condition_lines);
It looks to me like you have pointed a reference variable (vm.storedData) at another object, so since the value of data.condition_lines is still changing, so is the the storedData.
If you copy the contents of the condition_lines across to the storedData, you should get what you want.
You might want this:
https://docs.angularjs.org/api/ng/function/angular.copy