我想将状态加载为模态,以便我可以覆盖状态而不影响我的应用程序中的任何其他状态。例如,如果我有一个类似的链接:
<a ui-sref="notes.add" modal>Add Note</a>
然后我想使用指令中断状态更改:
.directive('modal', ['$rootScope', '$state', '$http', '$compile',
function($rootScope, $state, $http, $compile){
return {
priority: 0,
restrict: 'A',
link: function(scope, el, attrs) {
$rootScope.$on('$stateChangeStart', function (event, toState, toParams) {
event.preventDefault();
});
el.click(function(e){
$http
.get('URL HERE')
.then(function(resp){
$('<div class="modal">' + resp.data + '</div>').appendTo('[ui-view=app]');
setTimeout(function(){
$('.wrapper').addClass('showModal');
},1);
});
});
}
}
}
])
这会成功阻止状态更改并加载URL并将其作为模式附加到应用程序。 问题是它再次加载整个应用程序......
我如何只加载状态?例如模板文件和相邻的控制器。
状态如下:
.state('notes.add',
{
parent: 'notes',
url: '/add',
views: {
'content': {
templateUrl: 'partials/notes/add.html',
controller: 'NotesAddCtrl'
}
}
})
使用jQuery如何工作的示例:http://dev.driz.co.uk/AngularModal
了解如何通过AJAX访问StateA和StateB,使用History API更改URL以反映当前状态更改。
无论我是否在索引,StateA或StateB,我都可以将StateA或StateB作为模态加载(即使我已经在该状态上)并且它不会更改URL或者当前的内容,它只是覆盖了州内容。
这是我希望在AngularJS中能够做到的。
注意。此示例不能与浏览器后退和前进按钮一起使用,因为它是一个快速示例,而不是正确使用历史记录api。
答案 0 :(得分:2)
我几天前已经看过你的问题了,尝试设置一些可行的东西似乎很有趣。
我已将uiSref指令作为开头,并修改代码以使用angular-bootstrap的$ modal来显示所需的状态。
angular.module('ui.router.modal', ['ui.router', 'ui.bootstrap'])
.directive('uiSrefModal', $StateRefModalDirective);
function parseStateRef(ref, current) {
var preparsed = ref.match(/^\s*({[^}]*})\s*$/), parsed;
if (preparsed) ref = current + '(' + preparsed[1] + ')';
parsed = ref.replace(/\n/g, " ").match(/^([^(]+?)\s*(\((.*)\))?$/);
if (!parsed || parsed.length !== 4) throw new Error("Invalid state ref '" + ref + "'");
return { state: parsed[1], paramExpr: parsed[3] || null };
}
function stateContext(el) {
var stateData = el.parent().inheritedData('$uiView');
if (stateData && stateData.state && stateData.state.name) {
return stateData.state;
}
}
$StateRefModalDirective.$inject = ['$state', '$timeout', '$modal'];
function $StateRefModalDirective($state, $timeout, $modal) {
var allowedOptions = ['location', 'inherit', 'reload'];
return {
restrict: 'A',
link: function(scope, element, attrs) {
var ref = parseStateRef(attrs.uiSrefModal, $state.current.name);
var params = null, url = null, base = stateContext(element) || $state.$current;
var newHref = null, isAnchor = element.prop("tagName") === "A";
var isForm = element[0].nodeName === "FORM";
var attr = isForm ? "action" : "href", nav = true;
var options = { relative: base, inherit: true };
var optionsOverride = scope.$eval(attrs.uiSrefModalOpts) || {};
angular.forEach(allowedOptions, function(option) {
if (option in optionsOverride) {
options[option] = optionsOverride[option];
}
});
var update = function(newVal) {
if (newVal) params = angular.copy(newVal);
if (!nav) return;
newHref = $state.href(ref.state, params, options);
if (newHref === null) {
nav = false;
return false;
}
attrs.$set(attr, newHref);
};
if (ref.paramExpr) {
scope.$watch(ref.paramExpr, function(newVal, oldVal) {
if (newVal !== params) update(newVal);
}, true);
params = angular.copy(scope.$eval(ref.paramExpr));
}
update();
if (isForm) return;
element.bind("click", function(e) {
var button = e.which || e.button;
if ( !(button > 1 || e.ctrlKey || e.metaKey || e.shiftKey || element.attr('target')) ) {
e.preventDefault();
var state = $state.get(ref.state);
var modalInstance = $modal.open({
template: '<div>\
<div class="modal-header">\
<h3 class="modal-title">' + ref.state + '</h3>\
</div>\
<div class="modal-body">\
<ng-include src="\'' + state.templateUrl + '\'"></ng-include>\
</div>\
</div>',
controller: state.controller,
resolve: options.resolve
});
modalInstance.result.then(function (selectedItem) {
$scope.selected = selectedItem;
}, function () {
console.log('Modal dismissed at: ' + new Date());
});
}
});
}
};
}
您可以像<a ui-sref-modal="notes.add">Add Note</a>
指令要求angular-bootstrap
解析模态对话框。您需要在应用中使用ui.router.modal
模块。
答案 1 :(得分:1)
由于被要求提供我的评论的例子,
示例指令
myapp.directive('openModal', function ($modal) {
return function(scope, element, attrs) {
element[0].addEventListener('click', function() {
$modal.open({
templateUrl : attrs.openModal,
controller: attrs.controller,
size: attrs.openModalSize,
//scope: angular.element(element[0]).scope()
});
});
};
});
示例Html
<button
open-modal='views/poc/open-modal/small-modal.html'
open-modal-size='sm'
controller="MyCtrl">modal small</button>
上述指令方法与使用状态没有太大区别,该状态包含templateUrl
和controller
,但url不会更改。
.state('state1.list', {
url: "/list",
templateUrl: "partials/state1.list.html",
controller: function($scope) {
$scope.items = ["A", "List", "Of", "Items"];
}
})
答案 2 :(得分:-1)
显然存在Ui-sref not generating hash in URL (Angular 1.3.0-rc.3)引用的问题 https://github.com/angular-ui/ui-router/issues/1397
似乎根据评论修正了。
我个人不喜欢html5mode
因为它需要在您的服务器上进行额外的工作而没有明显的优势(我不认为将“更美丽的网址”作为证明额外工作的合理优势)。
使用路由器时还有另一个性能问题,即每次路由更改时都会重新创建视图DOM。我提到了一个很简单的解决方案 在this answer。
作为旁注,http://dev.driz.co.uk/AngularModal/中的示例表现不佳。它不记录历史,所以我不能回去。此外,如果单击索引或模式等链接,然后重新加载,则不会获得相同的页面。
更新。
从评论中可以看出,打开模态时不需要路线更改。在这种情况下,最简单的解决方案是不要将ui-sref
放在打开按钮上,让模态指令一起处理它。