मैं एक ऐसा फ़ंक्शन लिख रहा हूं जो HTML टेम्पलेट से ईमेल टेम्पलेट और कुछ जानकारी दी जा सकती है। इसके लिए मैं $compile
कोणीय के कार्य का उपयोग कर रहा हूं।
केवल एक समस्या है जिसे मैं हल नहीं कर सकता। टेम्पलेट में ng-include
की असीमित राशि वाला आधार टेम्पलेट होता है। जब मैं 'सर्वोत्तम अभ्यास' $timeout
(advised here) का उपयोग करता हूं तो यह काम करता है जब मैं सभी ng-include
को हटा देता हूं। तो यह वही नहीं है जो मैं चाहता हूं।
$ टाइमआउट उदाहरण:
return this.$http.get(templatePath)
.then((response) => {
let template = response.data;
let scope = this.$rootScope.$new();
angular.extend(scope, processScope);
let generatedTemplate = this.$compile(jQuery(template))(scope);
return this.$timeout(() => {
return generatedTemplate[0].innerHTML;
});
})
.catch((exception) => {
this.logger.error(
TemplateParser.getOnderdeel(process),
"Email template creation",
(<Error>exception).message
);
return null;
});
जब मैं टेम्पलेट इस समारोह टेम्पलेट्स कि अभी तक पूरी तरह संकलित नहीं कर रहे हैं (एक workarround $timeout
कार्यों घोंसला बनाने से है) वापस जाने के लिए शुरू होता है के लिए ng-include
के जोड़ने के लिए शुरू करते हैं। मेरा मानना है कि यह ng-include
की एसिंक प्रकृति की वजह से है।
कार्य कोड
यह कोड लौटाता है जब यह प्रतिपादन किया जाता है (समारोह अब पुन: उपयोग किया जा सकता है, see this question for the problem) एचटीएमएल टेम्पलेट। लेकिन यह समाधान एक बड़ा नहीं है क्योंकि यह $digest
के चल रहे हैं या नहीं, यह जांचने के लिए कोणीय निजी $$phase
का उपयोग कर रहा है। तो मैं सोच रहा हूं कि कोई अन्य समाधान है या नहीं?
return this.$http.get(templatePath)
.then((response) => {
let template = response.data;
let scope = this.$rootScope.$new();
angular.extend(scope, processScope);
let generatedTemplate = this.$compile(jQuery(template))(scope);
let waitForRenderAndPrint =() => {
if (scope.$$phase || this.$http.pendingRequests.length) {
return this.$timeout(waitForRenderAndPrint);
} else {
return generatedTemplate[0].innerHTML;
}
};
return waitForRenderAndPrint();
})
.catch((exception) => {
this.logger.error(
TemplateParser.getOnderdeel(process),
"Email template creation",
(<Error>exception).message
);
return null;
});
मैं क्या चाहता हूँ
मुझे लगता है कि ng-inlude
की असीमित मात्रा में संभाल सकता है और केवल वापसी जब टेम्पलेट सफलतापूर्वक बना दिया गया है एक कार्यक्षमता है करना चाहते हैं। मैं इस टेम्पलेट को प्रस्तुत नहीं कर रहा हूं और पूरी तरह से संकलित टेम्पलेट को वापस करने की आवश्यकता है।
समाधान
@estus जवाब के साथ प्रयोग करने के बाद मैं अंत में जब $ संकलन किया जाता है की जाँच का एक अन्य रास्ता मिल गया। इसके परिणामस्वरूप नीचे दिया गया कोड। $q.defer()
का उपयोग करने का कारण इस तथ्य के कारण है कि टेम्पलेट को किसी ईवेंट में हल किया गया है। इसके कारण मैं परिणाम को सामान्य वादे की तरह वापस नहीं कर सकता (मैं return scope.$on()
नहीं कर सकता)। इस कोड में एकमात्र समस्या यह है कि यह ng-include
पर भारी निर्भर करता है। यदि आप फ़ंक्शन को ऐसे टेम्पलेट की सेवा करते हैं जिसमें ng-include
$q.defer
कभी भी पुनर्स्थापित नहीं किया जाता है।
/**
* Using the $compile function, this function generates a full HTML page based on the given process and template
* It does this by binding the given process to the template $scope and uses $compile to generate a HTML page
* @param {Process} process - The data that can bind to the template
* @param {string} templatePath - The location of the template that should be used
* @param {boolean} [useCtrlCall=true] - Whether or not the process should be a sub part of a $ctrl object. If the template is used
* for more then only an email template this could be the case (EXAMPLE: $ctrl.<process name>.timestamp)
* @return {IPromise<string>} A full HTML page
*/
public parseHTMLTemplate(process: Process, templatePath: string, useCtrlCall = true): ng.IPromise<string> {
let scope = this.$rootScope.$new(); //Do NOT use angular.extend. This breaks the events
if (useCtrlCall) {
const controller = "$ctrl"; //Create scope object | Most templates are called with $ctrl.<process name>
scope[controller] = {};
scope[controller][process.__className.toLowerCase()] = process;
} else {
scope[process.__className.toLowerCase()] = process;
}
let defer = this.$q.defer(); //use defer since events cannot be returned as promises
this.$http.get(templatePath)
.then((response) => {
let template = response.data;
let includeCounts = {};
let generatedTemplate = this.$compile(jQuery(template))(scope); //Compile the template
scope.$on('$includeContentRequested', (e, currentTemplateUrl) => {
includeCounts[currentTemplateUrl] = includeCounts[currentTemplateUrl] || 0;
includeCounts[currentTemplateUrl]++; //On request add "template is loading" indicator
});
scope.$on('$includeContentLoaded', (e, currentTemplateUrl) => {
includeCounts[currentTemplateUrl]--; //On load remove the "template is loading" indicator
//Wait for the Angular bindings to be resolved
this.$timeout(() => {
let totalCount = Object.keys(includeCounts) //Count the number of templates that are still loading/requested
.map(templateUrl => includeCounts[templateUrl])
.reduce((counts, count) => counts + count);
if (!totalCount) { //If no requests are left the template compiling is done.
defer.resolve(generatedTemplate.html());
}
});
});
})
.catch((exception) => {
defer.reject(exception);
});
return defer.promise;
}
उत्तर के लिए धन्यवाद। फिर भी मुझे अपने फ़ंक्शन में दूसरे समाधान को एकीकृत करने का कोई तरीका नहीं दिख रहा है (मेरा विषय प्रश्न देखें)। समस्या यह है कि जब भी मैं अपने बनाए गए स्कोप ऑब्जेक्ट पर इवेंट घड़ी सेट करता हूं तो ईवेंट किसी भी घटना पर ट्रिगर नहीं होता है। क्या आपके पास एक उदाहरण है कि मुझे इसे अपने कार्य में कैसे एकीकृत करना चाहिए? ओह और आपका प्लंकर काम नहीं करता है। यह मुझे कोई एचटीएमएल आउटपुट नहीं देता है। –
प्लंक काम करता है। इसमें 'console.log' कथन हैं। कंसोल की जांच करें। मुझे यकीन नहीं है कि आप एकीकरण के बारे में क्या मतलब है। आपको स्कोप पर वॉचर्स सेट अप करने और केवल $ संकलन कॉल करने की आवश्यकता है। आदेश यहां कोई फर्क नहीं पड़ता है लेकिन पहले दर्शक को स्थापित करने का प्रयास करें। एक प्लंक प्रदान करने पर विचार करें जो समस्या को फिर से बना सकता है यदि यह आपके लिए काम नहीं करता है। किसी भी तरह, एनजी-शामिल 1.0 के बाद विरासत निर्देश है और यदि संभव हो तो इससे बचा जाना चाहिए क्योंकि यह वर्तमान कोणीय सर्वोत्तम प्रथाओं के अनुरूप नहीं है। – estus
मुझे पता चला कि इस तथ्य के कारण कि मैं $ रूटस्कोप का उपयोग कर रहा हूं। $ नया() (मेरे पास सेवा में कोई गुंजाइश नहीं है) घटनाओं को निकाल दिया नहीं जाता है। क्या आप जानते हैं कि क्यों और यदि $ रूटस्कोप इसका कारण बन रहा है, तो क्या आप कोई समाधान जानते हैं? http://plnkr.co/edit/ZEVSG7TBpYirR77UDxcF?p=preview –