डेटाबेस से गतिशील HTML स्ट्रिंग्स का संकलन


132

स्थिति

हमारे एंगुलर ऐप के भीतर नेस्टेड एक पेज है, जो एक कंट्रोलर द्वारा समर्थित पेज कहलाता है, जिसमें एनजी-बिंद-एचटीएमएल-असुरक्षित विशेषता वाला डिव होता है। इसे 'पेज कॉन्टेंट' नामक एक $ स्कोप var को सौंपा गया है। यह संस्करण एक डेटाबेस से गतिशील रूप से उत्पन्न HTML को असाइन करता है। जब उपयोगकर्ता अगले पृष्ठ पर फ़्लिप करता है, तो DB को एक कॉल किया जाता है, और इस नए HTML में पेजकॉन्टेंट संस्करण सेट किया जाता है, जो एनजी-बिंद-एचटीएमएल-असुरक्षित के माध्यम से ऑनस्क्रीन प्रदान किया जाता है। यहाँ कोड है:

पृष्ठ निर्देश

angular.module('myApp.directives')
    .directive('myPage', function ($compile) {

        return {
            templateUrl: 'page.html',
            restrict: 'E',
            compile: function compile(element, attrs, transclude) {
                // does nothing currently
                return {
                    pre: function preLink(scope, element, attrs, controller) {
                        // does nothing currently
                    },
                    post: function postLink(scope, element, attrs, controller) {
                        // does nothing currently
                    }
                }
            }
        };
    });

पृष्ठ निर्देश का टेम्प्लेट (" पृष्ठ। Html" टेम्प्लेट से ऊपर प्रॉपर्टी)

<div ng-controller="PageCtrl" >
   ...
   <!-- dynamic page content written into the div below -->
   <div ng-bind-html-unsafe="pageContent" >
   ...
</div>

पृष्ठ नियंत्रक

angular.module('myApp')
  .controller('PageCtrl', function ($scope) {

        $scope.pageContent = '';

        $scope.$on( "receivedPageContent", function(event, args) {
            console.log( 'new page content received after DB call' );
            $scope.pageContent = args.htmlStrFromDB;
        });

});

यह काम करता है। हम डीबी से पृष्ठ के HTML को ब्राउज़र में अच्छी तरह से प्रस्तुत करते हैं। जब उपयोगकर्ता अगले पृष्ठ पर जाता है, तो हम अगले पृष्ठ की सामग्री देखते हैं, और इसी तरह। अब तक सब ठीक है।

समस्या

यहाँ समस्या यह है कि हम एक पृष्ठ की सामग्री के अंदर संवादात्मक सामग्री रखना चाहते हैं। उदाहरण के लिए, HTML में एक थंबनेल छवि हो सकती है, जब उपयोगकर्ता उस पर क्लिक करता है, तो कोणीय को कुछ कमाल करना चाहिए, जैसे कि पॉप-अप मोडल विंडो प्रदर्शित करना। मैंने अपने डेटाबेस में कोणीय विधि कॉल (एनजी-क्लिक) को एचटीएमएल स्ट्रिंग्स में रखा है, लेकिन निश्चित रूप से एंगुलर या तो विधि कॉल या निर्देशों को पहचानने वाला नहीं है जब तक कि यह किसी तरह से HTML स्ट्रिंग को पार्स नहीं करता, उन्हें पहचानता है और उन्हें संकलित करता है।

हमारे डीबी में

पेज 1 के लिए सामग्री:

<p>Here's a cool pic of a lion. <img src="lion.png" ng-click="doSomethingAwesone('lion', 'showImage')" > Click on him to see a large image.</p>

पेज 2 के लिए सामग्री:

<p>Here's a snake. <img src="snake.png" ng-click="doSomethingAwesone('snake', 'playSound')" >Click to make him hiss.</p>

पेज कंट्रोलर में वापस, हम फिर इसी $ स्कोप फंक्शन को जोड़ते हैं:

पृष्ठ नियंत्रक

$scope.doSomethingAwesome = function( id, action ) {
    console.log( "Going to do " + action + " with "+ id );
}

मैं यह पता नहीं लगा सकता कि DB से HTML स्ट्रिंग के भीतर 'doSomethingAwesome' पद्धति को कैसे कॉल किया जाए। मुझे पता है कि कोणीय को HTML स्ट्रिंग को किसी तरह पार्स करना है, लेकिन कैसे? मैंने $ संकलित सेवा के बारे में अस्पष्ट अस्पष्ट पढ़ा है, और कुछ उदाहरणों की प्रतिलिपि बनाई और चिपकाई है, लेकिन कुछ भी काम नहीं करता है। साथ ही, अधिकांश उदाहरण गतिशील सामग्री को केवल निर्देशन के लिंकिंग चरण के दौरान सेट करते हुए दिखाते हैं। हम चाहते हैं कि ऐप के दौरान पेज ज़िंदा रहे। यह लगातार नई सामग्री प्राप्त करता है, संकलित करता है और प्रदर्शित करता है क्योंकि उपयोगकर्ता पृष्ठों के माध्यम से फ़्लिप करता है।

एक सार अर्थ में, मुझे लगता है कि आप कह सकते हैं कि हम एक कोणीय ऐप के भीतर कोणीय के गतिशील रूप से घोंसले की कोशिश कर रहे हैं, और उन्हें अंदर और बाहर स्वैप करने में सक्षम होने की आवश्यकता है।

मैंने कई बार कोणीय दस्तावेज के विभिन्न बिट्स, साथ ही साथ सभी प्रकार के ब्लॉग पोस्ट पढ़े हैं, और जेएस लोगों के कोड के साथ भरा हुआ है। मुझे नहीं पता कि क्या मैं पूरी तरह से कोणीय को गलत समझ रहा हूं, या बस कुछ सरल याद कर रहा हूं, या शायद मैं धीमा हूं। किसी भी मामले में, मैं कुछ सलाह का उपयोग कर सकता हूं।


2
$ संकलन और इसके आस-पास के डॉक्स ब्लॉग मुझे यह महसूस कराते हैं कि मैं भी धीमा हूँ - फिर भी मुझे लगता है कि मेरा js काफी मजबूत है - मुझे लगता है कि अगर मुझे इससे ग्रिप करने में दिक्कत होती है तो मैं एक बेवकूफ स्टाइल ब्लॉग बनाऊंगा - मेरी खासियत!
उतरा

जवाबों:


248

ng-bind-html-unsafeकेवल HTML के रूप में सामग्री प्रदान करता है। यह परिणामी DOM के लिए कोणीय दायरे को बांधता नहीं है। आपको $compileउस उद्देश्य के लिए सेवा का उपयोग करना होगा। मैंने इस प्लंकर को यह प्रदर्शित करने के $compileलिए बनाया कि उपयोगकर्ताओं द्वारा दर्ज किए गए निर्देशकीय रेंडर डायनामिक HTML बनाने के लिए कैसे उपयोग किया जाए और नियंत्रक के दायरे में बांध दिया जाए । स्रोत नीचे पोस्ट किया गया है।

demo.html

<!DOCTYPE html>
<html ng-app="app">

  <head>
    <script data-require="angular.js@1.0.7" data-semver="1.0.7" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.js"></script>
    <script src="script.js"></script>
  </head>

  <body>
    <h1>Compile dynamic HTML</h1>
    <div ng-controller="MyController">
      <textarea ng-model="html"></textarea>
      <div dynamic="html"></div>
    </div>
  </body>

</html>

script.js

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

app.directive('dynamic', function ($compile) {
  return {
    restrict: 'A',
    replace: true,
    link: function (scope, ele, attrs) {
      scope.$watch(attrs.dynamic, function(html) {
        ele.html(html);
        $compile(ele.contents())(scope);
      });
    }
  };
});

function MyController($scope) {
  $scope.click = function(arg) {
    alert('Clicked ' + arg);
  }
  $scope.html = '<a ng-click="click(1)" href="#">Click me</a>';
}

6
बहुत बहुत धन्यवाद, Buu! विशेषता निर्देश बनाना और स्कोप वॉच फ़ंक्शन को जोड़ना दो चीजें थीं जो मुझे याद आ रही थीं। अब जब यह काम कर रहा है, तो अनुमान लगाएं कि मैं निर्देश और $ संकलन पर फिर से पढ़ूंगा, यह समझने के लिए कि हुड के नीचे क्या चल रहा है।
जिराफ_सेंस

11
मुझे भी! इस पर डॉक्स को बेहतर बनाने के लिए कोणीय टीम वास्तव में कर सकती है।
क्रेग मॉर्गन

$compile(ele.contents())(scope);- इस लाइन ने कोणीय घटकों को संकलित न करने के मेरे मुद्दे को हल किया जो गतिशील रूप से जोड़े जाते हैं। धन्यवाद।
मितल प्रीतमणी

@BuuNguyen के अंदर teplateURL मान लीजिए अगर u में एनजी-बिंद-एचटीएमएल का उपयोग करके कुछ डायनेमिक htmnl पेज शामिल है, तो संकलित का उपयोग करते हुए कुछ असुरक्षित सामग्री को दूसरी तरफ से विश्वसनीय रूप से उपयोग किया जाता है।
शाम an ’’ १४:४५

1
मुझे यह उदाहरण पसंद है, लेकिन यह मेरा काम नहीं कर सकता है। मेरे पास एक स्विच स्टेटमेंट है जो उपयोगकर्ता की पसंद के कारण होता है इसलिए यह गतिशील है। उसके आधार पर मैं html युक्त निर्देश सम्मिलित करना चाहता हूं। निर्देश काम करता है अगर मैं इसे प्राकृतिक बूटस्ट्रैप चरण में रखता हूं। हालाँकि, मेरे पास यह है कि केवल फायरिंग नहीं है --- मामला 'जानकारी': $ गुंजाइश.htmlString = $ sce.trustAsHtml ('<div dynam = "htmlString"> dddzzz </ div>'); टूटना; --- जब मैं कुछ करना चाहता हूं --- $ संकलन ($ sce.trustAsHtml ('<div dynam = "htmlString"> dddzzz </ div>')); वर्कअराउंड आदि पर कोई विचार ...
उतरा

19

कोणीय 1.2.10 में लाइन scope.$watch(attrs.dynamic, function(html) {एक अमान्य चरित्र त्रुटि लौटा रही थी क्योंकि यह attrs.dynamicHTML टेक्स्ट का मान देखने की कोशिश कर रहा था।

मैंने तय किया कि गुण गुण गुंजाइश से प्राप्त करके

 scope: { dynamic: '=dynamic'}, 

मेरा उदाहरण है

angular.module('app')
  .directive('dynamic', function ($compile) {
    return {
      restrict: 'A',
      replace: true,
      scope: { dynamic: '=dynamic'},
      link: function postLink(scope, element, attrs) {
        scope.$watch( 'dynamic' , function(html){
          element.html(html);
          $compile(element.contents())(scope);
        });
      }
    };
  });

हैलो, अगर मैं का उपयोग element.html यह मेरे लौटने लेखन त्रुटि: अशक्त की नहीं कर सकते कॉल विधि 'insertBefore'। तो इसके बारे में कुछ गुगली करने के बाद मुझे पता चलता है कि मुझे element.append का उपयोग करना चाहिए, लेकिन अगर मैं कई स्थानों पर उस निर्देश का उपयोग करता हूं - तो यह कई गुना HTML उत्पन्न करता है। तो 2 निर्देश 4 एचटीएमएल कोड उत्पन्न करते हैं। आपके उत्तर के लिए धन्यवाद।
DzeryCZ

मैं आपके स्थान पर परिशिष्ट का उपयोग नहीं करूंगा, मैं आज रात उस पर एक नज़र डालूंगा और आपको वापस लाऊंगा। ईमानदार होने के लिए, मैंने इस निर्देश का उपयोग एक पृष्ठ में कुछ स्थानों पर बिना किसी समस्या के किया। मैं समस्या को पुन: उत्पन्न करने की कोशिश करूँगा और मैं आपके पास वापस आऊंगा।
अलेक्जेंड्रोस स्पाईरोपौलोस

1
@AlexandrosSpyropoulos मैं अभी परीक्षण करता हूं और देखता हूं कि मेरा कोड 1.2.12 के साथ भी ठीक चलता है। मुझे लगता है कि आप संभवतः HTML में घोषणा <div dynam = "html"> याद कर रहे हैं? (उस घोषणा के साथ, $ घड़ी गुंजाइश में 'HTML' संपत्ति देखती है, वास्तविक HTML नहीं जैसा कि आपने उल्लेख किया है, इसलिए कोई अमान्य चार त्रुटि नहीं होनी चाहिए।) यदि नहीं, तो मुझे वह प्लंकर भेजें जो दिखाता है कि यह काम नहीं करता है, मैं 'देखोगे क्या गलत है।
बुआ गुयेन

शायद तुम सही हो। मैं फिर से उम्मीद कर रहा हूं, कि html वास्तव में एक चर है जिसमें html: P शामिल है। हालांकि यह अच्छा है कि अपने निर्देशों पर एक गुंजाइश निर्धारित करें। umur.io/…
एलेक्जेंड्रो

$compile(ele.contents())(scope);- इस लाइन ने कोणीय घटकों को संकलित न करने के मेरे मुद्दे को हल किया जो गतिशील रूप से जोड़े जाते हैं। धन्यवाद।
मिताली प्रीतमणी १०'१४

5

एक Google चर्चा समूह में मिला। मेरे लिये कार्य करता है।

var $injector = angular.injector(['ng', 'myApp']);
$injector.invoke(function($rootScope, $compile) {
  $compile(element)($rootScope);
});

3

आप उपयोग कर सकते हैं

ng-bind-html https://docs.angularjs.org/api/ng/service/$sce

HTML को गतिशील रूप से बांधने का निर्देश। हालाँकि आपको $ sce सेवा के माध्यम से डेटा प्राप्त करना होगा।

कृपया http://plnkr.co/edit/k4s3Bx पर लाइव डेमो देखें

var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope,$sce) {
    $scope.getHtml=function(){
   return $sce.trustAsHtml("<b>Hi Rupesh hi <u>dfdfdfdf</u>!</b>sdafsdfsdf<button>dfdfasdf</button>");
   }
});

  <body ng-controller="MainCtrl">
<span ng-bind-html="getHtml()"></span>
  </body>

धन्यवाद! इससे मुझे मदद मिली। हालाँकि, आपको ngSanitize और कोणीय-sanitize.js शामिल करने की आवश्यकता है:var myApp = angular.module('myApp', ['ngSanitize']);
jaggedsoft

मेरे लिए भी काम करने के लिए बूटस्ट्रैप आइकन के दौरान सामग्री
md-

1

Html को attr के माध्यम से बाइंड करने के लिए नीचे दिए गए कोड की कोशिश करें

.directive('dynamic', function ($compile) {
    return {
      restrict: 'A',
      replace: true,
      scope: { dynamic: '=dynamic'},
      link: function postLink(scope, element, attrs) {
        scope.$watch( 'attrs.dynamic' , function(html){
          element.html(scope.dynamic);
          $compile(element.contents())(scope);
        });
      }
    };
  });

इस तत्व की कोशिश करें। html (गुंजाइश.डायनामिक); element.html से (attr.dynamic);

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.