【问题标题】:Remove Specific Item From Array With Class Objects Inside从包含类对象的数组中删除特定项目
【发布时间】:2019-12-04 07:26:14
【问题描述】:

我的问题

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

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

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

感谢收看。 约翰

【问题讨论】:

  • 使用ko.slice,根据文档,它与javascript的切片相同。此外,您可能应该删除“站”,因为您正在尝试访问我假设的对象的成员。试试 self.station()[i].name

标签: javascript arrays knockout.js


【解决方案1】:

你可以使用函数来找到它的索引看起来像:

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】:

你可以使用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);
}

【讨论】:

    【解决方案3】:

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

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

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

    【讨论】:

      【解决方案4】:

      很长一段时间的回答,我认为你遇到的问题是关于你声明的变量和你使用的变量类型不同,当你分配给你的对象时你没有使用它们的任何转换:

      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
      
          };
      

      但是你使用 assign 看起来像

            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>

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-01-09
        • 2021-08-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-21
        • 1970-01-01
        相关资源
        最近更新 更多