AngularJS - मैं प्रोग्रामेटिक रूप से एक नया, अलग-अलग स्कोप कैसे बना सकता हूं?


81

मैं Angular.factory के साथ एक अलर्ट बनाना चाहता हूं। मैंने एक html टेम्पलेट को फॉलो की तरह परिभाषित किया

var template = "<h1>{{title}}</h1>";

शीर्षक कॉल कंट्रोलर द्वारा प्रदान किया जाता है और अनुसरण के रूप में लागू किया जाता है

var compiled = $compile(template)(scope);
body.append(compiled);

तो, मैं नियंत्रक से कारखाने तक अलग-अलग गुंजाइश कैसे पारित कर सकता हूं? मैं कंट्रोलर फॉलो कोड में उपयोग कर रहा हूं

AlertFactory.open($scope);

लेकिन $ गुंजाइश वैश्विक नियंत्रक गुंजाइश चर है। मैं बस शीर्षक संपत्ति के साथ कारखाने के लिए एक छोटा सा दायरा पारित करना चाहता हूं।

धन्यवाद।

जवाबों:


107

आप मैन्युअल रूप से एक नया स्कोप बना सकते हैं।

$rootScopeयदि आप इसे इंजेक्ट करते हैं, या सिर्फ अपने कंट्रोलर स्कोप से आप एक नया स्कोप बना सकते हैं - यह बात अलग नहीं होनी चाहिए क्योंकि आप इसे अलग कर रहे हैं।

var alertScope = $scope.$new(true);
alertScope.title = 'Hello';

AlertFactory.open(alertScope);

यहां कुंजी पास trueहो रही है $new, जो एक पैरामीटर को स्वीकार करता है isolate, जो माता-पिता से विरासत के दायरे से बचा जाता है।

अधिक जानकारी यहां पाई जा सकती है: http://docs.angularjs.org/api/ng.$rootScope.Scope#$new


10
यदि आप मैन्युअल रूप से एक नया दायरा बनाते हैं, तो आप शायद इसे मैन्युअल रूप से नष्ट करने वाले हैं। मैन्युअल रूप से स्कोप नहीं बनाना बेहतर है।
मार्क राजकोक

मैंने एक परीक्षण किया है, लेकिन यह काम नहीं करता है। कृपया stackoverflow.com/questions/15565462/…
प्रीमियर

3
@MarkRajcok आप उल्लेख करते हैं कि मैन्युअल रूप से स्कोप नहीं बनाना बेहतर है। हालाँकि अगर आपको गतिशील रूप से html बनाने की आवश्यकता है और उस html के भीतर कोणीय निर्देश का उपयोग करना चाहते हैं तो क्या विकल्प है?
गुमशुदगी

जीवन रक्षक! ऐसा करना था, जैसा कि मैं कोणीय बूटस्ट्रैप मोडल के लिए एक आवरण लिख रहा था ।
जोनाथन

9
जब आप चाइल्ड स्कोप बनाते हैं (अलग-थलग या अलग नहीं), तो कोणीय अपने आप तब नष्ट हो जाता है जब उसके माता-पिता नष्ट हो जाते हैं। तो इस उदाहरण में, जब $scopeनष्ट हो alertScopeजाता है तो स्वचालित रूप से भी नष्ट हो जाता है। तो @MarkRajcok यह पूरी तरह से वैध उपयोग मामला है और पूरी तरह से सुरक्षित है।
jkjustjoshing

22

यदि आपको केवल चीजों को प्रक्षेपित करने की आवश्यकता है , तो $ संकलित के बजाय $ प्रक्षेप सेवा का उपयोग करें , और फिर आपको गुंजाइश की आवश्यकता नहीं होगी:

myApp.factory('myService', function($interpolate) {
    var template = "<h1>{{title}}</h1>";
    var interpolateFn = $interpolate(template);
    return {
        open: function(title) {
            var html = interpolateFn({ title: title });
            console.log(html);
            // append the html somewhere
        }
    }
});

परीक्षण नियंत्रक:

function MyCtrl($scope, myService) {
    myService.open('The Title');
}

बेला


2
$ संकलन और $ प्रक्षेप में क्या अंतर है? $ प्रक्षेप केवल पाठ की जगह बनाता है?
प्रीमियर

3
@Premier, यह मेरी समझ है। यह भी देखें stackoverflow.com/a/13460295/215945 यदि आपके टेम्पलेट में निर्देश हैं, तो $ इंटरपोलेट काम नहीं करेगा - इसके लिए आपको $ संकलन का उपयोग करने की आवश्यकता होगी।
मार्क राजकोक

ठीक है धन्यवाद। यह मेरे काम के लिए पर्याप्त नहीं है, मुझे पूरी गुंजाइश के साथ एक नियंत्रक की आवश्यकता है।
प्रीमियर

1
@Premier, मेरा सुझाव है कि आप जो कोशिश कर रहे हैं उसका एक बेला या प्लंकेर बनाने की कोशिश करें। यह स्पष्ट नहीं है कि आपका अलग-अलग दायरा कहां से आ रहा है।
मार्क राजकोक

अरे हाँ, मैं एक किया है stackoverflow.com/questions/15565462/...
प्रीमियर

2

निम्नलिखित कदम हैं:

  1. उपयोग करके अपने HTML को DOM में जोड़ें var comiledHTML = angular.element(yourHTML);
  2. यदि आप चाहते हैं तो एक नया स्कोप बनाएं var newScope = $rootScope.$new();
  3. $ Comile () को कॉल करें; फ़ंक्शन जो लिंक फ़ंक्शन लौटाता हैvar linkFun = $compile(comiledHTML);
  4. लिंकफुन कहकर नए दायरे को बांधें var finalTemplate = linkFun(newScope);
  5. अपने DOM के लिए FinalTemplate परिशिष्ट करें YourHTMLElemet.append(finalTemplate);

1
से var linkFun = $compile(comiledHTML);चरण 2 पर
iamdevlinph

2

मेरे प्लंकर को देखें। मैं प्रोग्रामेटिक रूप से एक रेंडर निर्देश के साथ विजेट निर्देश उत्पन्न कर रहा हूं।

https://plnkr.co/edit/5T642U9AiPr6fJthbVpD??==view

angular
  .module('app', [])
  .controller('mainCtrl', $scope => $scope.x = 'test')
  .directive('widget', widget)
  .directive('render', render)

function widget() {
  return {
    template: '<div><input ng-model="stuff"/>I say {{stuff}}</div>'
  }
}

function render($compile) {
  return {
    template: '<button ng-click="add()">{{name}}</button><hr/>',
    link: linkFn
  }

  function linkFn(scope, elem, attr) {
    scope.name = 'Add Widget';
    scope.add = () => {
      const newScope = scope.$new(true);
      newScope.export = (data) => alert(data);
      const templ = '<div>' +
                      '<widget></widget>' +
                      '<button ng-click="export(this.stuff)">Export</button>' +
                    '</div>';
      const compiledTempl = $compile(templ)(newScope);
      elem.append(compiledTempl);
    }
  }
}

1

मुझे लगता है जब आप एक अलग दायरे के बारे में बात कर रहे हैं तो आप एक निर्देश के बारे में बात कर रहे हैं।

यह कैसे करना है इसका एक उदाहरण है। http://jsfiddle.net/rgaskill/PYhGb/

var app = angular.module('test',[]);

app.controller('TestCtrl', function ($scope) {
    $scope.val = 'World';
});

app.factory('AlertFactory', function () {

    return {
        doWork: function(scope) {
            scope.title = 'Fun';    
            //scope.title = scope.val;  //notice val doesn't exist in this scope
        }
    };

});

app.controller('DirCtrl', function ($scope, AlertFactory) {
    AlertFactory.doWork($scope);  
});

app.directive('titleVal',function () {
    return {
        template: '<h1>Hello {{title}}</h1>',
        restrict: 'E',
        controller: 'DirCtrl',
        scope: {
            title: '='
        },
        link: function() {

        }
    };

});

मूल रूप से, एक नियंत्रक को एक निर्देश में संलग्न करें जिसने एक अलग-अलग गुंजाइश को परिभाषित किया है। डायरेक्टिव कंट्रोलर में इंजेक्ट किया गया स्कोप एक अलग स्कोप होगा। निर्देश नियंत्रक में आप अपने अलर्ट के साथ अलर्ट कर सकते हैं, जिसमें आप अलग-अलग गुंजाइश पास कर सकते हैं।


grrr..plnkr.co अभी ऑफ़लाइन लगता है। उम्मीद है कि लिंक अभी भी काम करता है जब यह वापस आता है।
rgaskill

मुझे लगता है कि यह मेरे लिए एक अच्छा समाधान नहीं है, मुझे निर्देश की आवश्यकता नहीं है। मुझे मोडल अलर्ट डायलॉग दिखाने के लिए फैक्ट्री कैपैबल्स की जरूरत है। इसलिए मुझे डोम ओवरले में टेम्पलेट HTML संलग्न करने और चेतावनी दृश्य में डेटा प्रबंधित करने के लिए एक नियंत्रक का उपयोग करने की आवश्यकता है।
प्रीमियर

2
मेरा तर्क है कि आपको कारखाने में डोम में हेरफेर नहीं करना चाहिए। आप अपने व्यापार तर्क के साथ अपने विचार तर्क को मिला रहे हैं। आप वास्तव में वही कर सकते हैं जो आपने एक निर्देश में वर्णित किया है जिसमें डोम हेरफेर होना चाहिए।
rgaskill

ब्रैड ग्रीन का एक निर्देश के बजाय एक मोडल के लिए एक सेवा का उपयोग करने के बारे में एंडी को उत्तर दें: blog.angularjs.org/2012/11/about-those-directives.html
मार्क राजकोक

... लेकिन इस विशिष्ट बूटस्ट्रैप मामले के लिए, मुझे लगता है कि यह एक निर्देश के साथ सबसे अच्छा हल है। plnkr.co/edit/z4J8jH?p=preview
rgaskill
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.