2016-01-19 5 views
0

Здесь я пытаюсь передать ссылку на нокаут, наблюдаемую на сортируемый объект, который является частью jQueryUI и не имеет доступа к переменной по умолчанию.Передача нокаута, наблюдаемая на jQueryUI сортируемая

В примере кода я пытаюсь сделать ссылку на viewModel через self на линии self.dragMode(true);. Строка подсвечивается в примере кода.

Произошедшие вызовы потерпели неудачу, и всякий раз, когда я вызываю объект, на который ссылаюсь, я получаю undefined. Каков правильный способ сделать это?

var viewModel = function() { 
 
    var self = this; 
 
    self.gridItems = ko.observableArray(
 
    [{ 
 
     "rowItems": [{ 
 
     "name": "Item 1" 
 
     }, { 
 
     "name": "Item 2" 
 
     }, { 
 
     "name": "Item 3" 
 
     }] 
 
    }, { 
 
     "rowItems": [{ 
 
     "name": "Item 4" 
 
     }] 
 
    }, { 
 
     "rowItems": [{ 
 
     "name": "Item 5" 
 
     }, { 
 
     "name": "Item 6" 
 
     }] 
 
    }] 
 
); 
 
    self.selectedRowItem = ko.observable(); 
 
    self.dragMode = ko.observable(false); 
 

 
    console.log(self.gridItems()); 
 

 
    self.gridItems().splice(0, 0, { 
 
    "rowItems": [{ 
 
     "placeholder": true, 
 
     "name": "" 
 
    }] 
 
    }); 
 

 
    for (var i = 1; i < self.gridItems().length; i++) { 
 
    console.log(self.gridItems()[i]); 
 
    self.gridItems()[i].rowItems.splice(0, 0, { 
 
     "placeholder": true, 
 
     "name": "" 
 
    }); 
 
    for (var j = 1; j < self.gridItems()[i].rowItems.length; j++) { 
 
     self.gridItems()[i].rowItems.splice(j + 1, 0, { 
 
     "placeholder": true, 
 
     "name": "" 
 
     }); 
 
     j++; 
 
    } 
 
    self.gridItems().splice(i + 1, 0, { 
 
     "rowItems": [{ 
 
     "placeholder": true, 
 
     "name": "" 
 
     }] 
 
    }); 
 
    i++; 
 
    } 
 

 
    console.log(self.gridItems()); 
 
}; 
 

 
//connect items with observableArrays 
 
ko.bindingHandlers.sortableList = { 
 
    self: this, 
 
    init: function(element, valueAccessor, allBindingsAccessor, context) { 
 
    $(element).data("sortList", valueAccessor()); //attach meta-data 
 
    $(element).sortable({ 
 
     start: function(event, ui) { 
 
     \t self.dragMode(true); // HERE NEED TO ACCESS VIEWMODEL 
 
     }, 
 
     update: function(event, ui) { 
 
     var item = ui.item.data("sortItem"); 
 
     if (item) { 
 
      //identify parents 
 
      var originalParent = ui.item.data("parentList"); 
 
      var newParent = ui.item.parent().data("sortList"); 
 
      //figure out its new position 
 
      var position = ko.utils.arrayIndexOf(ui.item.parent().children(), ui.item[0]); 
 
      if (position >= 0) { 
 
      if (newParent[position].placeholder) { 
 
      \t originalParent.remove(item); 
 
      \t newParent.splice(position, 0, item); 
 
      } else { 
 
      \t return; 
 
      } 
 
      } 
 

 
      ui.item.remove(); 
 
     } 
 
     }, 
 
     cancel: ':input,button,.contenteditable,.sortable-placeholder-horizontal,.sortable-placeholder-vertical', 
 
     connectWith: '.sortable-container' 
 
    }); 
 
    } 
 
}; 
 

 
//attach meta-data 
 
ko.bindingHandlers.sortableItem = { 
 
    init: function(element, valueAccessor) { 
 
    var options = valueAccessor(); 
 
    $(element).data("sortItem", options.item); 
 
    $(element).data("parentList", options.parentList); 
 
    } 
 
}; 
 

 
ko.applyBindings(new viewModel());
.sortable-grid .sortable { 
 
    list-style-type: none; 
 
    margin: 0; 
 
    padding: 0; 
 
    width: 100% !important; 
 
    display: table !important; 
 
    table-layout: auto; 
 
} 
 

 
.sortable-grid .sortable .sortable-item { 
 
    margin: 0 3px 3px 3px; 
 
    padding: 0.4em; 
 
    font-size: 1.4em; 
 
    cursor: move; 
 
} 
 

 
.sortable-grid .sortable div.fixed { 
 
    cursor: default; 
 
    color: #959595; 
 
    opacity: 0.5; 
 
} 
 

 
.sortable-grid { 
 
    
 
} 
 

 
.sortable-grid .sortable .sortable-row { 
 
    height: 100% !important; 
 
    padding: 0 !important; 
 
    margin: 0 !important; 
 
    display: table-row !important; 
 
} 
 

 
.sortable-grid .sortable .sortable-item { 
 
    border: 1px solid green; 
 
    //width:initial; 
 
    display: table-cell; 
 
    margin: 0 !important; 
 
} 
 

 
.sortable-grid .sortable .sortable-item > p { 
 
    //width:100%; 
 
    display: inline; 
 
    margin: 0 !important; 
 
    z-index: 9999; 
 
    cursor: text; 
 
} 
 

 
.sortable-grid .sortable .sortable-placeholder-horizontal { 
 
    background-color: red; 
 
} 
 

 
.sortable-grid .sortable .sortable-placeholder { 
 
    background-color: red; 
 
    display: table-cell; 
 
    margin: 0 !important; 
 
    width:10px !important; 
 
} 
 

 
.sortable-grid .sortable .sortable-placeholder:hover { 
 
    background-color: blue; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<link href="https://code.jquery.com/ui/1.12.0-beta.1/themes/smoothness/jquery-ui.css" rel="stylesheet" /> 
 
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.js"></script> 
 
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css" rel="stylesheet" /> 
 
<link href="https://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet" /> 
 
<script src="https://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> 
 

 
<div class="" data-bind="template: { name: 'gridTmpl', foreach: gridItems, templateOptions: { parentList: gridItems} }, sortableList: gridItems"> 
 
</div> 
 

 
<script id="gridTmpl" type="text/html"> 
 
    <div class="sortable-grid"> 
 
    <div class="sortable sortable-container"> 
 
     <div class="sortable-row sortable sortable-container" data-bind="template: { name: 'rowTmpl', foreach: rowItems, templateOptions: { parentList: rowItems} }, sortableList: rowItems"> 
 
     </div> 
 
    </div> 
 
    </div> 
 
</script> 
 

 
<script id="rowTmpl" type="text/html"> 
 
    <!-- ko if: !$data.placeholder --> 
 
    <div class="sortable-item" data-bind="sortableItem: { item: $data, parentList: $data.parentList }"> 
 
    <p class="contenteditable" contenteditable="true" data-bind="text: name"></p> 
 
    </div> 
 
    <!-- /ko --> 
 
    <!-- ko if: $data.placeholder && $root.dragMode --> 
 
    <div class="sortable-placeholder" data-bind="sortableItem: { item: $data, parentList: $data.parentList }"> 
 
    </p> 
 
    </div> 
 
    <!-- /ko --> 
 
</script>

ответ

0

В этом случае необходимо было использовать bindingContext, в котором содержится ссылка на глобальный viewModel. Аргумент viewModel не может использоваться, потому что контекст изменился в зависимости от того, где шаблон используется локально.

Наконец, это были все необходимые изменения, чтобы получить viewModel и передать его в JQuery Сортируемый:

  1. $(element).data("viewModel", bindingContext.$root);
  2. var viewModel = ui.item.parent().data("viewModel");

Обновлено связывание обработчика:

//connect items with observableArrays 
ko.bindingHandlers.sortableList = { 
    init: function(element, valueAccessor, allBindings, viewModel, bindingContext) { 
    $(element).data("sortList", valueAccessor()); //attach meta-data 
    $(element).data("viewModel", bindingContext.$root);// ? bindingContext.$root : bindingContext); //attach meta-data 
    $(element).sortable({ 
     start: function(event, ui) { 
     //identify viewModel 
     var viewModel = ui.item.parent().data("viewModel"); 
     viewModel.dragMode(true); 
     }, 
     change: function(event, ui) { 
     //identify viewModel 
     var viewModel = ui.item.parent().data("viewModel"); 
     viewModel.dragMode(true); 
     }, 
     update: function(event, ui) { 
     var item = ui.item.data("sortItem"); 
     if (item) { 

      //identify parents 
      var originalParent = ui.item.data("parentList"); 
      var newParent = ui.item.parent().data("sortList"); 
      //identify viewModel 
      var viewModel = ui.item.parent().data("viewModel"); 
      //figure out its new position 
      var position = ko.utils.arrayIndexOf(ui.item.parent().children(), ui.item[0]); 
      if (position >= 0) { 
      console.log(newParent[position]); 
      if (newParent[position].placeholder) { 
       console.log(originalParent); 
       originalParent.remove(item); 
       newParent.splice(position, 0, item); 
       viewModel.dragMode(false); 
      } else { 
       return; 
      } 
      } 

      ui.item.remove(); 
     } 
     }, 
     cancel: ':input,button,.contenteditable,.sortable-placeholder-horizontal,.sortable-placeholder-vertical', 
     connectWith: '.sortable-container' 
    }); 
    } 
}; 
1

Аргументы для ko.bindingHandlers.yourBindingName являются: element, valueAccessor, allBindings, viewModel, bindingContext (отсюда - knockoutjs manual).

В вашем коде вы, вероятно, имеете его как аргумент context.

Таким образом, вы можете изменить self.dragMode(true); на context.dragMode(true), и он должен работать.

+0

Простое изменение 'context.dragMode (true);' не исправить, но я посмотрю онлайн-ресурс! –

 Смежные вопросы

  • Нет связанных вопросов^_^