ng-model 一次只从一个选项卡保存到 webSQL 数据库

ng-model only saving from one Tab to webSQL db at a time

我正在使用带有选项卡式界面的 Ionic。 Tab 1有一些基本数据,Tab 2有一些更详细的数据。

我正在使用这样的数据库插入:

$scope.insert = function(date_in, basic_data1, basic_date2, detail1, detail2, detail3) {
db.transaction(function(tx){
  tx.executeSql("INSERT OR REPLACE INTO 'stats' (date, age, gender, val1, val2, val3) VALUES (?,?,?,?,?,?)", [date_in, basic_data1, basic_date2, detail1, detail2, detail3);
  },function(e){
    $log.log("ERROR: " + e.message);
  });
}

这可以从您所在的选项卡插入数据。这是 ng-click:

ng-click="insert(currentDate, userage, usergender, user_detail1, user_detail2, user_detail3)" 

以及表单元素:

<label class="item item-input">
        <i class="icon ion-clock"></i> 
        <span class="input-label smalltext"> Age</span>
        <input type="number" ng-model="userage">
      </label>

我正在 Chrome 开发控制台中查看 webSQL 数据库。插入有效,它会像它应该的那样覆盖。但它只保存您所在选项卡中的数据库部分。

例如如果我从选项卡 1 中保存日期、年龄和性别。如果我从选项卡 2 保存日期和详细信息 1、2 和 3 保存。这 用 "undefined" 覆盖了 数据的另一部分,甚至认为返回到另一个选项卡显示数据仍在字段中。

日期有效的原因是两个选项卡上都有一个日期选择器绑定到同一模型 - currentDate。

我怎样才能让我的函数每次都处理两个选项卡中的数据?我在使用 jQM 时从未遇到过这个问题...

这是控制器中的代码:

.controller('SettingsCtrl', function($scope, $rootScope, $localstorage, $log, $ionicPopup, $ionicActionSheet, $timeout, $cordovaDatePicker) {
$scope.insert = function(date_in, weight_in, heartrate_in, sysbp_in, diabp_in, neck_in, chest_in, biceps_in, waist_in, forearms_in, thighs_in, calves_in) {
console.log(date_in, weight_in, heartrate_in, sysbp_in, diabp_in, neck_in, chest_in, biceps_in, waist_in, forearms_in, thighs_in, calves_in);
db.transaction(function(tx){
  tx.executeSql("INSERT OR REPLACE INTO 'stats' (date, weight, heartrate, sysbp, diabp, neck, chest, biceps, waist, forearms, thighs, calves) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)", [date_in, weight_in, heartrate_in, sysbp_in, diabp_in, neck_in, chest_in, biceps_in, waist_in, forearms_in, thighs_in, calves_in]);
  console.log("The inserted weight is", weight_in);
  console.log("The inserted date is", date_in);
  console.log("The inserted neck is", neck_in);
  console.log("The inserted chest is", chest_in);
  },function(e){
    $log.log("ERROR: " + e.message);
  });
}

 $scope.data = {};

$scope.select = function(date) {
db.transaction(function(tx){
  tx.executeSql("SELECT date, weight, heartrate, sysbp, diabp, chest, biceps, waist, forearms, thighs, calves FROM stats where date =?", [date, weight, heartrate, sysbp, diabp, chest, biceps, waist, forearms, thighs, calves]);
  console.log("The inserted weight is", y);
  },function(e){
    $log.log("ERROR: " + e.message);
  });       
}

$scope.usergender = $localstorage.get('storeGender');
$scope.userage = parseInt($localstorage.get('storeAge'));
$scope.userheight = parseInt($localstorage.get('storeHeight'));
$scope.userunits = $localstorage.get('storeUnits');
$scope.userdate = $localstorage.get('storeDate');
$scope.useranalytics = $localstorage.get('storeAnalytics');

$scope.changeVal = function(storeName, val){
$localstorage.set(storeName,val);
console.log(storeName + " is now " + val);
}

 // Date converter UK or US //
 Date.prototype.dateConvertUK = function() {
function two(n) {
  return (n < 10 ? '0' : '') + n;
}
return two(this.getDate()) + '/' + two(this.getMonth() + 1) + '/' + this.getFullYear();
};

Date.prototype.dateConvertUS = function() {
function two(n) {
  return (n < 10 ? '0' : '') + n;
}
return two(this.getMonth() + 1) + '/' + two(this.getDate()) + '/' + this.getFullYear();
  };

 var dateTypeUK = true;

// Set todays date
  var d = new Date();
 console.log("New Date is", d);
 if(dateTypeUK===true){
   today = d.dateConvertUK();
    console.log("Today (coverted UK) is", today);
  }else{
   today = d.dateConvertUS();
  console.log("Today (coverted US) is", today);
 } 

 $scope.currentDate = today;

 //Convert date to string
 $scope.dateToString = function(date){
 return date.toString();
} 

var options = {
date: new Date(),
mode: 'date', // or 'time'
minDate: new Date() - 10000,
allowOldDates: true,
allowFutureDates: false,
doneButtonLabel: 'DONE',
doneButtonColor: '#F2F3F4',
cancelButtonLabel: 'CANCEL',
cancelButtonColor: '#000000'
 };

$scope.popupDate = function(){
   console.log("in the popup");
  $cordovaDatePicker.show(options).then(function(date){
     $scope.currentDate = date;
     console.log("processed date is", date);
  });
}   

});

而 html 中的代码是:

<ion-view view-title="Vitals">
<ion-nav-buttons side="secondary">
  <button class="button smalltext" ng-click="popupDate()">
    <i class="icon ion-calendar"></i> {{currentDate}}
  </button>
</ion-nav-buttons>
<ion-content class="padding" has-bouncing="false">
<div class="list">
<label class="item item-input">
    <i class="icon ion-podium"></i>
    <span class="input-label smalltext">Weight (<span id="weightunit">kg</span>)</span>
    <input type="number" ng-model="data.userweight" placeholder="0">kg
  </label>
  <div class="item item-button-right smalltext">
    Your BMI is: high 
    <button class="button button-stable button-clear">
      <i class="icon ion-help-circled"></i>
    </button>
  </div>
</div>
<div class="list">
  <label class="item item-input">
    <i class="icon ion-heart"></i>
    <span class="input-label smalltext">Heart Rate (bpm)</span>
    <input type="number" ng-model="data.userheartrate" placeholder="0">
  </label>
  <div class="item item-button-right smalltext">
    Your Heart Rate is: 
    <button class="button button-stable button-clear">
      <i class="icon ion-help-circled"></i>
    </button>
  </div>
</div>
<div class="list">
  <div class="item item-divider smalltext">
    <i class="icon ion-stats-bars"></i> Blood Pressure
  </div>
  <div class="row">
        <div class="col noPadding">
          <label class="item item-input">
            <i class="icon ion-arrow-up-b"></i>
            <span class="input-label smalltext">Systolic</span>
            <input type="number" placeholder="0" ng-model="data.usersysbp">
          </label>
        </div>
        <div class="col noPadding">
          <label class="item item-input">
            <i class="icon ion-arrow-down-b"></i>
            <span class="input-label smalltext">Diastolic</span>
            <input type="number" placeholder="0" ng-model="data.userdiabp">
          </label>
        </div>    
  </div>          
  <div class="item item-button-right smalltext">
    Your Blood Pressure is: 
    <button class="button button-stable button-clear">
      <i class="icon ion-help-circled"></i>
    </button>
  </div>
</div>
    <button class="button button-mygreen button-full" ng-click="insert(currentDate, data.userweight, data.userheartrate, data.usersysbp, data.userdiabp, data.userneck, data.userchest, data.userbiceps, data.userwaist, data.userforearms, data.userthighs, data.usercalves)">
      <i class="icon ion-android-archive"></i> Save
    </button>
  </ion-content>
</ion-view>

由于每个选项卡都包含在 ng-if 中,因此每个选项卡都会创建自己的范围。因此,每个选项卡仅在其范围内具有其具有输入标签的属性。当您调用插入方法(我假设它是在选项卡的父范围内创建的)时,只会定义选项卡上的属性。

要解决此问题,请在与保存数据的插入函数相同的范围内创建一个对象,然后修改选项卡上的输入以引用该数据:

因此,您的选项卡父级的控制器将是:

.controller('tabmanager', function($scope) {
    $scope.insert = function(date_in, basic_data1, basic_date2, detail1, detail2, detail3) {
         db.transaction(function(tx){
             tx.executeSql("INSERT OR REPLACE INTO 'stats' (date, age, gender, val1, val2, val3) VALUES (?,?,?,?,?,?)", [date_in, basic_data1, basic_date2, detail1, detail2, detail3);
         },function(e){
              $log.log("ERROR: " + e.message);
         });
    }
    $scope.data = {};  //an empty object to hold your model data in this scope
})

您的标记更改为:

<label class="item item-input">
    <i class="icon ion-clock"></i> 
    <span class="input-label smalltext"> Age</span>
    <input type="number" ng-model="data.userage">
</label>
....
....
<button ng-click="insert(data.currentDate, data.userage, data.usergender, data.user_detail1, data.user_detail2, data.user_detail3)">Save</button>

我认为基本上问题在于每个选项卡都有自己的数据模型,并且在另一个选项卡中定义的数据不适用于此选项卡,因此当您在选项卡 2 中使用 gender 时,它是未定义。

我对 angular 及其约定还很陌生,但是有什么可以阻止您将 $rootScope 也传递给控制器​​,如下所示:
.controller('TabxCtrl', function ($scope, $rootScope) {
并让两个选项卡控制器共享此 $rootScope?

然后您可以只使用 $rootScope.data 来定义在任一选项卡中设置的值,这样当您执行数据库 INSERT none 时,这些值是未定义的。

不确定你的应用程序的其余部分是如何构建的,但你可以利用
$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams){ ... })
事件以确保在离开选项卡之前将最新的字段值保存到 $rootScope.data 变量。或者您可以在任何字段值更改或更新时更新 $rootScope.data 变量。

我过去使用过 jQM,所以我理解你的感受。我在同一条船上想知道优势是否超过新的学习曲线哈哈。
祝你好运!