从包含类对象的数组中删除特定项目



我的问题

我正在尝试从我的数组中删除一个特定的项目,但是,我的数组包含我无法处理的其他对象。

我像这样定义一个"站":

/* CLASS Station 
* @param  id       int   unique id this station
* @param  name     str   name of the station
* @param  location obj   the position of the station
*                        in the workflow diagram
*/
var Station = function(id, name, posX=null, posY=null) {
  this.id     = ko.observable(id || self.getUniqueId());
  this.name   = ko.observable(name);
  this.posX   = ko.observable(posX);
  this.posY   = ko.observable(posY);
};

所以我使用这个函数在我的数组中添加了一个站......

.
.
 self.addStation(new Station(76, "Receiving", 0, 10));

现在,我想知道如何通过传递名称从数组中删除,如下所示:

 self.removeStation("Receiving");

我想不通。我已经研究了这里的所有链接,但没有运气。

整个源代码

// CLASS Workflow
var Workflow = function(id, status){
    this.status = status || false;
    this.id = id;
}

/* CLASS Station 
* @param  id       int   unique id this station
* @param  name     str   name of the station
* @param  location obj   the position of the station
*                        in the workflow diagram
*/
var Station = function(id, name, posX=null, posY=null) {
  this.id     = ko.observable(id || self.getUniqueId());
  this.name   = ko.observable(name);
  this.posX   = ko.observable(posX);
  this.posY   = ko.observable(posY);
};

  // CLASS ViewModel 
  var ViewModel = function(workFlowId) {
    var self = this; // Scope Trick


    /*******************************
     * Observables
     *-----------------------------*/
    self.station = ko.observableArray();
    /*******************************
     * Initialize The Builder
     *-----------------------------*/
    self.workflowId = ko.observable();
    /*******************************
     * Arrays
     *-----------------------------*/
    self.workflow    = ko.observableArray();
    /*******************************
     * Actions
     *-----------------------------*/

    /* Method: initWorkflow
    *
    *  Desc: When the user gets to the builder
    *  page, we have to configure a Workflow.
    *  If they are loading a saved one, the ID
    *  will be passed. If they are starting a new
    *  one, we will give it a unique ID.
    *
    *  @param   int workFlowId  The id of the workflow
    *  @return  int workFlowId  The id is returned
    */  
    self.initWorkflow = function(workFlowId, status=false) {
      var id;
      if(!workFlowId){
        /* Call Function to generate unique ID */
        id = self.getUniqueId();
      } else {
        id = workFlowId;
      }
      /* Set ID */
      this.workflowId = id;
      this.workflow = new Workflow(id, status); 
    };

    /*------------------------------------------------------- 
    *  Method: addStation
    *
    *  Desc: Adds a station to current workflow
    *  @param    station   object  A station object
    *--------------------------------------------------------*/
    self.addStation = function(station){
      self.station.push(station);
    }

    /* Remove Station - */
    self.removeStation = function (Name) {
      for( var i = 0; i < self.station().length; i++){ 
        console.dir("In Remove Function: " + self.station()[i]);
     }
  }

    /*------------------------------------------------------- 
    *  Method: getUniqueId
    *
    *  Desc: Generates a random unique Id
    *  @returns  id   int   A unique random ID
    *--------------------------------------------------------*/
    self.getUniqueId = function(){
      var id = new Date().getTime();
      console.group("In Funtion: self.getUniqueId");
      console.log("Returned unique id of: " + id);
      console.groupEnd("In Funtion: self.getUniqueId");
      return id;
    }

    /* Start it up */
    self.initWorkflow(workFlowId);
    //------------------------
    //  UNIT TESTING
    //------------------------
    //........ STATION RELATED ..........................
    // 1. Add
    self.addStation(new Station(76, "Receiving", 0, 10));
    // 2. Remove
    self.removeStation("Receiving");

  }  // end ViewModel

  // Instantiate the ViewModel
  window.view_model = new ViewModel();
  // Away we go...
  ko.applyBindings(window.view_model);

我似乎无法掌握数组中的名称:

// DON'T WORK
self.station()[i].Station.name

谢谢你的关注。John

u可以使用函数来查找其索引,如下所示:

function arrayFirstIndexOf(array, predicate, predicateOwner) {
    for (var i = 0, j = array.length; i < j; i++) {
        if (predicate.call(predicateOwner, array[i])) {
            return i;
        }
    }
    return -1;
}

然后在您的/* Remove Station - */中,编辑代码如下所示:

/* Remove Station - */
    self.removeStation = function (Name) {
    var index = arrayFirstIndexOf(self.station(), function(item){
        return item.name === Name;   
    });
    index > -1 && self.station.splice(index, 1);
}

希望这个帮助!

您可以使用ko.utils.arrayRemoveItem从数组中删除您需要首先找到它的项目

/* Remove Station  */
self.removeStation = function (search) {
    // find the station
    var foundStation = ko.utils.arrayFirst(this.station, function(item) {
        return ko.utils.stringStartsWith(item.name().toLowerCase(), search);
    });
    // remove the station
    ko.utils.arrayRemoveItem(this.station, foundStation);
}

感谢您的回复。但是我使用以下代码找到了可以接受的问题解决方案:

/* Remove Station  */
    self.removeStation = function (Name) {
      var c = -1;
      ko.utils.arrayForEach(this.station(), function(item) {
        c++;
        var value = item.name();
        if(value==Name){
          console.log("found it! at index " + c);
          self.station().splice(c,1);
        }
    });
    // Force the UI to update
    self.station.valueHasMutated();
  }

我意识到这不是最干净或最有效的解决方案,但它似乎有效。我很想知道如何优化它,但这超出了我的工资等级,哈哈。

sry longy回答,我认为你得到的问题是关于你声明的变量和你使用的变量不是同一类型,当你分配给你的对象时,你不使用它们的任何转换,如下所示:

var Station = function(id, name, posX=null, posY=null) {
      this.id     = ko.observable(id || self.getUniqueId()); //observalbe declared
      this.name   = ko.observable(name);//observalbe declared
      this.posX   = ko.observable(posX);//observalbe declared
      this.posY   = ko.observable(posY);//observalbe declared
    };

但随后您使用分配看起来像

      var newObj = {
        id: "82",
        name: "Updated Name",
        posX: 92,
        posY: 88
      }
self.modifyStation("name","Shipping",newObj);

分配它时:

objNewItem.id = oldId;  // Put old ID back in
    self.station.push(objNewItem); //not convert its properties to observable will make some errors on binding html.

我用你的例子做了一个工作JSFILDLE,请阅读它,当你不明白哪一部分时回复。 希望这有帮助。

function arrayFirstIndexOf(array, predicate, predicateOwner) {
    for (var i = 0, j = array.length; i < j; i++) {
        if (predicate.call(predicateOwner, array[i])) {
            return i;
        }
    }
    return -1;
}
// CLASS Workflow
var Workflow = function(id, status) {
  this.status = status || false;
  this.id = id;
}
/* CLASS Field 
 * @param  id             int    unique id this station
 * @param  fieldType      str    type of input
 * @param  fieldName      obj    name of the input
 * @param options         array  options array
 */
var Field = function(fieldId, fieldType, fieldName, options) {
  this.fieldId = ko.observable(fieldId);
  this.fieldType = ko.observable(fieldType);
  this.fieldName = ko.observable(fieldName);
  this.options = ko.observableArray(options);
};
/* CLASS Station 
 * @param  id       int   unique id this station
 * @param  name     str   name of the station
 * @param  location obj   the position of the station
 *                        in the workflow diagram
 */
var Station = function(id, name, posX = null, posY = null, fields) {
  this.id = ko.observable(id || self.getUniqueId());
  this.name = ko.observable(name);
  this.posX = ko.observable(posX);
  this.posY = ko.observable(posY);
  this.fields = ko.observableArray(fields || []);
};
// CLASS ViewModel 
var ViewModel = function(workFlowId) {
  var self = this; // Scope Trick

  /*******************************
   * Observables
   *-----------------------------*/
  self.fieldId = ko.observable();
  self.fieldName = ko.observable();
  self.fieldType = ko.observable();
  /*******************************
   * Initialize The Builder
   *-----------------------------*/
  self.workflowId = ko.observable();
  /*******************************
   * Arrays
   *-----------------------------*/
  self.workflow = ko.observableArray();
  self.station = ko.observableArray();
  self.fields = ko.observableArray();
  /*******************************
   * Computed Observables
   *-----------------------------*/
  /*******************************
   * Actions
   *-----------------------------*/
  /* Method: initWorkflow
   *
   *  Desc: When the user gets to the builder
   *  page, we have to configure a Workflow.
   *  If they are loading a saved one, the ID
   *  will be passed. If they are starting a new
   *  one, we will give it a unique ID.
   *
   *  @param   int workFlowId  The id of the workflow
   *  @return  int workFlowId  The id is returned
   */
  self.initWorkflow = function(workFlowId, status = false) {
    var id;
    if (!workFlowId) {
      /* Call Function to generate unique ID */
      id = self.getUniqueId();
    } else {
      id = workFlowId;
    }
    /* Set ID */
    this.workflowId = id;
    this.workflow = new Workflow(id, status);
  };
  /*------------------------------------------------------- 
   *  Method: addStation
   *
   *  Desc: Adds a station to current workflow
   *  @param    station   object  A station object
   *--------------------------------------------------------*/
  self.addStation = function(station) {
    self.station.push(station);
  }
  
  /* Remove Station  */
  self.removeStation = function(Name) {
    var index = arrayFirstIndexOf(self.station(), function(item){
        return item.name() === Name;   
    });
    index > -1 && self.station.splice(index, 1);
  }
  /* Update A Station ** NEEDS FIXING **
   *
   *  @param   findBy      string    Property to find ( "id" or "name")
   *  @param   cmpVal      string    Value to compare against
   *  @param   objNewItem  object    The new object replacing old
   * */
  self.modifyStation = function(findBy, cmpVal, objNewItem) {
    var sourceIndex;
    var oldId;
    var found = false;
    /* Find Index Of Old Station */
    var c = -1;
    ko.utils.arrayForEach(this.station(), function(item) {
      c++;
      switch (findBy) {
        case "id":
          var value = ko.unwrap(item.id);
          if (value == cmpVal) {
            sourceIndex = c;
            oldId = value;
            found = true;
          }
          break;
        case "name":
          var value = ko.unwrap(item.name);
          if (value == cmpVal) {
            sourceIndex = c;
            oldId = ko.unwrap(item.id);
            found = true;
          }
          break;
      }
    });
    /* Remove Old */
    if (found === true) {
      self.station().splice(sourceIndex, 1);
      /* Insert New Station 
       *  [For Now] not allowing updating of ID. Only
       *  can update the other properties (yes, I realize that
       *  only leaves "name", but more will be added )
       */
      objNewItem.id(oldId); // Put old ID back in
      self.station.push(objNewItem);
    } else {
      alert(cmpVal + " was not found in array!");
    }
  }
  self.addField = function(stationId, newField) {
    var c = -1;
    found = false;
    ko.utils.arrayForEach(this.station(), function(item) {
      c++;
      var value = ko.unwrap(item.id);
      console.log(value, c);
      if (value == stationId) {
        //console.log("found it! at index " + c);
        self.station()[c].fields.push(newField);
      }
    });
    self.station.valueHasMutated();
  };
  self.modifyField = function(stationId, oldFieldId, newObjField) {
    // TO DO
  };
  self.removeField = function(field) {
    self.fields.remove(field);
  };

  

  /* Perform Test On Button Click */
  self.doTest = function() {
    self.removeStation("Shipping");
  }
  self.doTest2 = function() {
    var newObj = {
      id: ko.observable("82"),
      name: ko.observable("Updated Name"),
      posX: ko.observable(92),
      posY: ko.observable(88),
      fields: ko.observableArray([])
    }
    self.modifyStation("name", "Shipping", newObj);
    self.station.valueHasMutated();
  }
  // Add Fields
  self.doTest3 = function() {
    var objNewField = {
      fieldId: 456,
      fieldName: "Last Name",
      fieldType: "Text"
    }
    self.addField(86, objNewField);
  }
  /*------------------------------------------------------- 
   *  Method: getUniqueId
   *
   *  Desc: Generates a random unique Id
   *  @returns  id   int   A unique random ID
   *--------------------------------------------------------*/
  self.getUniqueId = function() {
    var id = new Date().getTime();
    console.group("In Funtion: self.getUniqueId");
    console.log("Returned unique id of: " + id);
    console.groupEnd("In Funtion: self.getUniqueId");
    return id;
  }
  /*------------------------------------------------------- 
   *  Method: debugAll
   *
   *  Desc: Console Logs Our View Model
   *--------------------------------------------------------*/
  this.debugAll = function() {
    console.group("Debug:");
    // Workflow
    console.group("Current Workflow Id")
    console.log("self.workflowId = " + self.workflowId);
    console.groupEnd("Current Workflow Id")
    // Stations
    console.group("Stations In This Workflow")
    console.table(self.station());
    console.groupEnd("Stations In This Workflow")
    // Fields
    console.groupEnd("Debug:");
  }
  /* Start it up */
  self.initWorkflow(workFlowId);
  //------------------------
  //  UNIT TESTING
  //------------------------
  //........ STATION RELATED ..........................
  // 1. Add
  self.addStationShipping = function() {
    self.addStation(new Station(86, "Shipping", 0, 10, [{
      fieldId: 45,
      fieldName: "First Name",
      fieldType: "Text"
    }]));
  }
  self.addStation(new Station(76, "Receiving", 0, 10, null));
  self.addStationShipping();
  /* Dump ViewModel */
  self.debugAll();
  //----------------------------------------------------------------

} // end ViewModel
// Instantiate the ViewModel
window.view_model = new ViewModel(1213131212);
// Away we go...
ko.applyBindings(window.view_model);
// Page Utility Functions
function wait(ms) {
  var start = new Date().getTime();
  var end = start;
  while (end < start + ms) {
    end = new Date().getTime();
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<div>
  <ul data-bind="foreach: station">
    <li data-bind="text: 'id: ' + id()"></li>
    <li data-bind="text: 'name: ' +name()"></li>
    <li data-bind="text: 'posX: ' +posX()"></li>
    <li data-bind="text: 'posY: ' +posY()"></li>
    <ul data-bind="foreach: fields">
      <li data-bind="text: fieldId"></li>
      <li data-bind="text: fieldName"></li>
      <li data-bind="text: fieldType"></li>
    </ul>
  </ul>
</div>
<button data-bind="click: doTest">Remove "Shipping" From Station Array</button>
<button data-bind="click: doTest2">Update "Shipping" In Station Array</button>
<hr>
<h3>Test: Add Field To Shipping Station</h3>
<button data-bind="click: function() { addStationShipping()}">Add Shpping</button>
<button data-bind="click: doTest3()">Add Field</button>

最新更新