Как добавить элементы Angular -enabled в DOM?

Я хотел бы добавить программные элементы DOM с Angular -enabled. На самом деле, вероятно, мне нужно будет добавить пользовательские компоненты. Как я могу это сделать?

Вот тривиальная сценария, чтобы продемонстрировать проблему: http://jsfiddle.net/ZJSz4/2/

HTML:

<div ng-app="main">
    <div ng-controller="MyCtrl">
        <button ng-click="add()" >Add</button>
        <div id="container">
            <div>{{test}}</div>
        </div>
    </div>
</div>

JS:

angular.module("main", []).controller("MyCtrl", function($scope) {
    $scope.add = function() {
        $("#container").append("<div>{{test}}</div>");
    };

    $scope.test = 'Test Message';
});

На всякий случай, я ожидаю, что он добавит div, показывающий "Test Message" для каждого клика - не {{test}}.

Зачем мне это нужно? Ну, я хотел бы иметь несколько сортируемых столбцов (в jQuery сортируемом смысле) с портлетами. Я предполагаю, что каждый портлет может быть компонентом.

Я поднимаюсь на неправильный холм? Что такое Angular способ решить эту проблему?

EDIT. Я надеялся, что этот упрощенный пример не закончится так, но в любом случае. Конечной целью является не отображение div для каждого элемента в массиве.

Чего я действительно хочу, это более сложный контроллер. Мне нужен контейнер портлетов с интересным поведением. Возможно, потребуется решить разместить каждый портлет в другом столбце. Он может предлагать изменение макета и иметь достойный способ реорганизации портлетов в таком случае. И так далее.

Ответ 1

Хотя я не совсем уверен, каков желаемый результат, вы хотите быть уверенным, что все манипуляции с DOM выполняются внутри директивы, а не внутри вашего контроллера.

Этот пример JSfiddle должен помочь вам в правильном направлении.

http://jsfiddle.net/ZJSz4/5/

<div ng-app="main">
<div ng-controller="MyCtrl">
<div id="container">
    <button ng-click="add()" >Add</button>
    <ng-portlet></ng-portlet>
</div>
</div>

angular.module("main", []).controller("MyCtrl", function($scope) {
    $scope.test = 'Test Message';
}).directive("ngPortlet", function ($compile) {
return {
    template: '<div>{{test}}</div>   ',
    restrict: 'E',
    link: function (scope, elm) {
        scope.add = function(){
            console.log(elm);
           elm.after($compile('<ng-portlet></ng-portlet>')(scope));
        }
    }
};
});

Ответ 2

Если вы хотите несколько тестов, я бы предложил настроить его так.

<div ng-app="main">
    <div ng-controller="MyCtrl">
        <button ng-click="add()" >Add</button>
        <div id="container">
            <div ng-repeat="test in tests">{{test.name}}</div>
        </div>
    </div>
</div>


$scope.tests = []; // define this as an array

$scope.add = function() {
   var newTest = {name: 'Test Message'};

   $scope.tests.push(newTest);
};

Это будет динамически создавать divs на основе вашего объекта test.

Ответ 3

Как отметил @Christopher Marshall, самый простой способ сделать это - использовать повторяющийся элемент и нажимать новый предмет в область действия на кнопке.

[HTML]

<div ng-app="main">
    <div ng-controller="MyCtrl">
        <button ng-click="add()" >Add</button>
        <div id="container">
            <div ng-repeat="test in tests">{{test}}</div>
        </div>
    </div>
</div>

[JS]

angular.module("main", []).controller("MyCtrl", function($scope) {
    $scope.add = function() {
        $scope.tests.push('New Message');
    };

    $scope.tests = ["Test Message","Test Message 2"];
});