从内部带有类对象的数组中删除特定项

时间:2019-07-26 00:44:50

标签: javascript arrays knockout.js

我的问题

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

我正在这样定义一个“工作站”:

/* 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

感谢您的光临。 约翰

4 个答案:

答案 0 :(得分:1)

您可以使用9 10150 9,875从需要首先找到它的阵列中删除它

ko.utils.arrayRemoveItem

答案 1 :(得分:0)

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 - */ u编辑代码中如下所示:

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

希望获得帮助!

答案 2 :(得分:0)

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

/* 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();

  }

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

答案 3 :(得分:0)

很久没回答了,我认为您遇到的问题是有关您声明的变量和您使用的变量类型不同,并且当您将u分配给您的对象时,您不使用它们的任何转换:

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>