Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angularjs/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angularjs 角度选项卡-可排序/可移动_Angularjs_Angularjs Directive - Fatal编程技术网

Angularjs 角度选项卡-可排序/可移动

Angularjs 角度选项卡-可排序/可移动,angularjs,angularjs-directive,Angularjs,Angularjs Directive,是否存在允许对其重新排序的任何JS制表符指令(如浏览器的制表符) 如果不是的话,一个开始的实现将是伟大的 使用 如何使它们可重新标定 编辑:添加了Bounty以使用上面的原始选项卡集语法。至少有两种方法可以实现它 第一。转到并下载引导选项卡。Bootstrap UI是用Angularjs编写的,包含许多有用的模块。虽然您必须自己实现一些代码来动态添加新选项卡,但这应该很简单。只需使用ng click创建一个按钮/div,它调用一个动态添加新选项卡的函数 第二。用ng repeat自己实现它。

是否存在允许对其重新排序的任何JS制表符指令(如浏览器的制表符)

如果不是的话,一个开始的实现将是伟大的

使用


如何使它们可重新标定


编辑:添加了Bounty以使用上面的原始选项卡集语法。

至少有两种方法可以实现它

第一。转到并下载引导选项卡。Bootstrap UI是用Angularjs编写的,包含许多有用的模块。虽然您必须自己实现一些代码来动态添加新选项卡,但这应该很简单。只需使用ng click创建一个按钮/div,它调用一个动态添加新选项卡的函数

第二。用ng repeat自己实现它。下面是一些伪代码,说明它的外观

HTML:

<div class="tabs" ng-controller="TabController">
   <div class="add-tab" ng-click="add_tab()"></div>

   <div ng-repeat="tab in tabs" class="tab"></div>
</div>

Controller(JS):

app.controller('TabController',['$scope', function($scope){
$scope.tabs = [1, 1]
$scope.add_tab = function(){
$scope.tabs.push(1);
}
}]);
HTML:
控制器(JS):
app.controller('TabController',['$scope',函数($scope){
$scope.tabs=[1,1]
$scope.add_tab=函数(){
$scope.tabs.push(1);
}
}]);
关于可排序的部分。您可以创建自己的排序表(基本上为选项卡提供一个可拖动组件,如果您这样做,您应该将其作为一个指令编写),使用jQuery,或者使用一些Angularjs排序表/拖动表,通过搜索很容易找到。

我对此做了一个。 为此,我使用了来自的角度指令。我也曾经让它更容易

剩下要做的就是连接所有这些


我希望这个例子可以帮助您。

如果您不想使用Angular UI,比如说出于大小原因,您可以推出自己的基本版本。演示正在进行中

资料 你说你不需要标签页是动态的,但这可能会使它们更易于重用。因此,在包装范围内,您可以:

$scope.tabs = [{
  header: 'Tab A',
  content: 'Content of Tab A'
},{
  header: 'Tab B',
  content: 'Content of Tab B'
}, {
  header: 'Tab C',
  content: 'Content of Tab C'
}];
标签HTML 在设计HTML结构时,可以对按钮和内容重复上面的列表

<tabs>
  <tab-buttons>
    <tab-button ng-repeat="tab in tabs">{{tab.header}}</tab-button>
  </tab-buttons>
  <tab-contents>
    <tab-content ng-repeat="tab in tabs">{{tab.content}}</tab-body>
  </tab-contents>
</tabs>
假设您在页面中有正确的CSS,特别是
类的样式。当前的
类在此时有一组工作选项卡

可恶的 使用HTML5拖放API,您可以进行一些基本的拖放操作,而不用担心鼠标位置之类的问题。首先要做的是设计使其工作所需的属性。在这种情况下,引用列表的父项上的
sortable
属性,以及包含引用当前项索引的
sortable item
属性

<tabs sortable="tabs">
  <tab-buttons>
    <tab-button ng-repeat="tab in list" sortable-item="$index">{{tab.header}}</tab-button>
  </tab-buttons>
  <tab-contents>
    <tab-content ng-repeat="tab in list">{{tab.content}}</tab-body>
  </tab-contents>
</tabs>
我们需要注意的要点是,每个
sortableItem
只需要知道其当前索引。如果它检测到另一个项目被丢弃在它上面,那么它会调用
可排序
控制器上的一个函数,然后在外部作用域上对数组重新排序
ngRepeat
然后执行常规操作并移动选项卡


尽管我怀疑有更简单的解决方案,但这个解决方案将可排序行为和选项卡行为完全解耦。您可以对不属于
选项卡的元素使用
sortable
,也可以使用
选项卡
,而不使用可排序行为。

使用角度UI引导
选项卡集
,仅使用
sortable选项卡
指令:

<tabset>
  <tab sortable-tab ng-repeat="tab in tabs" heading="{{tab.title}}" active="tab.active" disabled="tab.disabled">
    <p>{{tab.content}}</p>
  </tab>
  <tab disabled="true">
    <tab-heading>
      <i class="glyphicon glyphicon-plus"></i>
    </tab-heading>
  </tab>
</tabset>
然后还可以查看作用域上的
$index
变量,以确保始终具有当前元素的最新索引:

var index = scope.$index;
scope.$watch('$index', function(newIndex) {
  index = newIndex;
});
然后使用,通过
setData
getData

attrs.$set('draggable', true);

// Wrapped in $apply so Angular reacts to changes
var wrappedListeners = {
  // On item being dragged
  dragstart: function(e) {
    e.dataTransfer.effectAllowed = 'move';
    e.dataTransfer.dropEffect = 'move';
    e.dataTransfer.setData('application/json', index);
    element.addClass('dragging');
  },
  dragend: function(e) {
    e.stopPropagation();
    element.removeClass('dragging');
  },

  dragleave: function(e) {
    element.removeClass('hover');
  },
  drop: function(e) {
    e.preventDefault();
    e.stopPropagation();
    var sourceIndex = e.dataTransfer.getData('application/json');
    move(sourceIndex, index);
    element.removeClass('hover');
  }
};

// For performance purposes, do not
// call $apply for these
var unwrappedListeners = {
  dragover: function(e) {
    e.preventDefault();
    element.addClass('hover');
  },
  /* Use .hover instead of :hover. :hover doesn't play well with 
     moving DOM from under mouse when hovered */
  mouseenter: function() {
    element.addClass('hover');
  },
  mouseleave: function() {
    element.removeClass('hover');
  }
};

angular.forEach(wrappedListeners, function(listener, event) {
  element.on(event, wrap(listener));
});

angular.forEach(unwrappedListeners, function(listener, event) {
  element.on(event, listener);
});

function wrap(fn) {
  return function(e) {
    scope.$apply(function() {
      fn(e);
    });
  };
}
注意:对于一些悬停效果,使用
悬停
类而不是
:hover
,存在一些问题。这部分是由于CSS
:悬停
样式从鼠标下重新排列后,没有在元素上删除,至少在Chrome中是这样

用于实际移动选项卡的函数,获取
ngRepeat
使用的数组,并对其重新排序:

function move(fromIndex, toIndex) {
  // http://stackoverflow.com/a/7180095/1319998
  tabs.splice(toIndex, 0, tabs.splice(fromIndex, 1)[0]);
};

您可以看到所有这些

很抱歉没有澄清,但可排序的功能是我没有想到的,因此是标题的焦点。添加标签很容易,是的,这将是引导和指令当然。我从问题中删除了动态添加选项卡,这样就不会有更多的混乱。感谢是有意义的。我假设您不喜欢使用jQuery来完成它。我曾经写过一个原生的Angularjs draggable,但因为使用jQuery更容易、更美观、更广泛的浏览器支持和更好的性能,所以我把它删掉了。否则,如果你想写你自己的,一个很好的开始做它的地方angularjs本机,他们有一个可拖动的演示那里。您可以使用它,然后对移动对象实现一些约束。这不是一个糟糕的实现,但有点过火。我试着换掉我现有的angularui选项卡集,结果它破坏了UI。在我的案例中,这必须从一开始就使用。我增加了100个悬赏,如果你能想到一个指令覆盖在angular ui选项卡上,你能使用原始angular ui
tabset
指令而不分解生成的标记吗?请看额外的奖金谢谢你的解决方案我真的很高兴看到它在plunkr工作。不过我有一个小问题,即在包装好的dragstart侦听器中未定义数据传输。当我比较plunkr中的调用堆栈和我自己的调用堆栈时,我发现在您的示例中angular.js触发事件,在我的调用堆栈中jquery.js触发事件。知道为什么吗?如果使用jQuery,事件可能会被包装。您可能必须在侦听器中使用
e=e.originalEvent
才能访问本机事件对象。正则表达式无法正确匹配my ng repeat:
ng repeat=“tab in vm.tabsCollection”
我想它会尝试确保变量以“s”结尾,而“collection”则不会。此外,它不是直接在作用域上,作用域['vm.tabscolection']无法访问嵌套的道具,所以我只是删除了这个hack并使用:
var tabs=scope['vm']['tabscolection']| scop
// Attempt to integrate with ngRepeat
// https://github.com/angular/angular.js/blob/master/src/ng/directive/ngRepeat.js#L211
var match = attrs.ngRepeat.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);
var tabs;
scope.$watch(match[2], function(newTabs) {
  tabs = newTabs;
});
var index = scope.$index;
scope.$watch('$index', function(newIndex) {
  index = newIndex;
});
attrs.$set('draggable', true);

// Wrapped in $apply so Angular reacts to changes
var wrappedListeners = {
  // On item being dragged
  dragstart: function(e) {
    e.dataTransfer.effectAllowed = 'move';
    e.dataTransfer.dropEffect = 'move';
    e.dataTransfer.setData('application/json', index);
    element.addClass('dragging');
  },
  dragend: function(e) {
    e.stopPropagation();
    element.removeClass('dragging');
  },

  dragleave: function(e) {
    element.removeClass('hover');
  },
  drop: function(e) {
    e.preventDefault();
    e.stopPropagation();
    var sourceIndex = e.dataTransfer.getData('application/json');
    move(sourceIndex, index);
    element.removeClass('hover');
  }
};

// For performance purposes, do not
// call $apply for these
var unwrappedListeners = {
  dragover: function(e) {
    e.preventDefault();
    element.addClass('hover');
  },
  /* Use .hover instead of :hover. :hover doesn't play well with 
     moving DOM from under mouse when hovered */
  mouseenter: function() {
    element.addClass('hover');
  },
  mouseleave: function() {
    element.removeClass('hover');
  }
};

angular.forEach(wrappedListeners, function(listener, event) {
  element.on(event, wrap(listener));
});

angular.forEach(unwrappedListeners, function(listener, event) {
  element.on(event, listener);
});

function wrap(fn) {
  return function(e) {
    scope.$apply(function() {
      fn(e);
    });
  };
}
function move(fromIndex, toIndex) {
  // http://stackoverflow.com/a/7180095/1319998
  tabs.splice(toIndex, 0, tabs.splice(fromIndex, 1)[0]);
};