को .js फ़ाइल के सापेक्ष कोणीय निर्देश टेम्पलेट


85

मैं एक कोणीय निर्देशन का निर्माण कर रहा हूं जिसका उपयोग कुछ अलग स्थानों में किया जाएगा। मैं हमेशा उस एप्लिकेशन की फ़ाइल संरचना की गारंटी नहीं दे सकता जो निर्देश का उपयोग किया जाता है, लेकिन मैं उपयोगकर्ता को उसी फ़ोल्डर में directive.jsऔर directive.html(वास्तविक फ़ाइल नाम नहीं) डालने के लिए बाध्य कर सकता हूं ।

जब पृष्ठ इसका मूल्यांकन करता है directive.js, तो यह templateUrlस्वयं के सापेक्ष माना जाता है। क्या फ़ाइल के templateUrlसापेक्ष सेट करना संभव है directive.js?

या यह केवल निर्देश में टेम्पलेट को शामिल करने के लिए अनुशंसित है।

मैं सोच रहा हूं कि मैं अलग-अलग परिस्थितियों के आधार पर अलग-अलग टेम्प्लेट लोड करना चाहता हूं, इसलिए अपडेट करने के बजाय रिश्तेदार पथ का उपयोग करने में सक्षम होना पसंद करेंगे directive.js


4
या फिर आप अपने टेम्पलेट को js में बदलने के लिए grunt-html2js का उपयोग कर सकते हैं, जिसे AngularJs अपने टेम्पलेट कैश में कैश करेगा। यह कोणीय-उई लोग क्या करते हैं।
Beyers

महान विचार से परे, मैं grunt-html2js के बारे में नहीं जानता था। इसकी जांच कराएंगे।
पेडलपेट

जवाबों:


76

वर्तमान में निष्पादित स्क्रिप्ट फ़ाइल हमेशा स्क्रिप्ट सरणी में अंतिम एक होगी, जिससे आप आसानी से इसका मार्ग पा सकते हैं:

// directive.js

var scripts = document.getElementsByTagName("script")
var currentScriptPath = scripts[scripts.length-1].src;

angular.module('app', [])
    .directive('test', function () {
        return {
            templateUrl: currentScriptPath.replace('directive.js', 'directive.html')
        };
    });

यदि आप सुनिश्चित नहीं हैं कि स्क्रिप्ट नाम क्या है (उदाहरण के लिए यदि आप एक से अधिक स्क्रिप्ट्स को पैक कर रहे हैं), तो इसका उपयोग करें:

return {
    templateUrl: currentScriptPath.substring(0, currentScriptPath.lastIndexOf('/') + 1) 
        + 'directive.html'
};

नोट : ऐसे मामलों में जहां एक क्लोजर का उपयोग किया जाता है, आपका कोड यह सुनिश्चित करने के लिए बाहर होना चाहिए कि करंटस्क्रिप्ट का सही समय पर मूल्यांकन किया गया है, जैसे:

// directive.js

(function(currentScriptPath){
    angular.module('app', [])
        .directive('test', function () {
            return {
                templateUrl: currentScriptPath.replace('directive.js', 'directive.html')
        };
    });
})(
    (function () {
        var scripts = document.getElementsByTagName("script");
        var currentScriptPath = scripts[scripts.length - 1].src;
        return currentScriptPath;
    })()
);

2
ओह, अब यह बहुत अच्छा है! दुर्भाग्य से, यह मेरी js फ़ाइलों को पैकिंग और मिनिमाइज़ करने के साथ टूट जाएगा, है ना? इसके अलावा, 'वर्तमान में स्क्रिप्ट फ़ाइल हमेशा अंतिम एक ही क्यों होती है'? मैं इस धारणा के तहत था कि सभी स्क्रिप्ट फाइलें वैश्विक दायरे में भरी हुई हैं।
पेडालपेटे

1
जब ब्राउज़र एक <script>टैग का सामना करता है, तो पृष्ठ को रेंडर करने के लिए जारी रखने से पहले इसे तुरंत निष्पादित करता है, इसलिए वैश्विक स्क्रिप्ट गुंजाइश में, अंतिम <script>टैग हमेशा अंतिम होता है।
Alon Gubkin

1
इसके अलावा, इसे छोटा करने पर नहीं टूटना चाहिए, लेकिन इसे पैकिंग पर तोड़ना चाहिए, इसलिए मैंने इसका एक समाधान जोड़ा है
Alon Gubkin

मुझे लगता है कि मैं देख रहा हूं कि आपका क्या मतलब है। आप यह मान रहे थे कि मैं एक ही स्क्रिप्ट टैग के भीतर पृष्ठ में सब कुछ लोड कर रहा था। यह मामला नहीं है, लेकिन मैं उसके आसपास काम कर सकता हूं। एक महान और रचनात्मक जवाब के लिए धन्यवाद!
पेडलपेट

1
स्क्रिप्ट का नाम बदलने के बजाय, आप path = currentScriptPath.split("/"); path.pop(); path.push("directive.html");फ़ाइल नामों पर कोई निर्भरता नहीं रख सकते , और "directive.js", "/directive.js" और "path / to / directive.js" का समर्थन करते हैं। कोड गोल्फ प्रतियोगिता को एक एकल विवरण (ब्याह, एट अल का उपयोग करके) में संयोजित करना है।
नाथन मैकइंसन

6

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

<div my-directive my-template="template"></div>

फिर $compile(template)(scope)निर्देश के अंदर कुछ का उपयोग करें ।


मुझे यकीन नहीं है कि मुझे आज ही इस बात की सूचना मिल गई है कि MWay, जवाब न देने के लिए क्षमा करें। क्या आप सुझाव दे रहे हैं कि निर्देश वस्तु के भीतर, मेरे पास कई टेम्पलेट हैं? और फिर $compileजो भी टेम्प्लेट उत्तीर्ण करने की विधि को इंगित करता है ? मुझे $compileवैसे भी उपयोग करना पड़ सकता है , इसलिए यह एक अच्छा सुझाव हो सकता है।
पेडालपेटे

4

Alon Gubkin के उत्तर के अलावा, मैं स्क्रिप्ट के पथ को संग्रहीत करने और इसे निर्देश में इंजेक्ट करने के लिए एक तत्काल-इनवॉल्ड फ़ंक्शन अभिव्यक्ति का उपयोग करके एक निरंतर परिभाषित करने का सुझाव दूंगा:

angular.module('app', [])

.constant('SCRIPT_URL', (function () {
    var scripts = document.getElementsByTagName("script");
    var scriptPath = scripts[scripts.length - 1].src;
    return scriptPath.substring(0, scriptPath.lastIndexOf('/') + 1)
})())

.directive('test', function(SCRIPT_URL) {
    return {
        restrict :    'A',
        templateUrl : SCRIPT_URL + 'directive.html'
    }
});

3

यह कोड एक फाइल में है, जिसे मार्ग.जेएस कहा जाता है

निम्नलिखित ने मेरे लिए काम नहीं किया:

var scripts = document.getElementsByTagName("script")
var currentScriptPath = scripts[scripts.length-1].src;
var baseUrl = currentScriptPath.substring(0, currentScriptPath.lastIndexOf('/') + 1);

निम्नलिखित ने किया:

var bu2 = document.querySelector("script[src$='routes.js']");
currentScriptPath = bu2.src;
baseUrl = currentScriptPath.substring(0, currentScriptPath.lastIndexOf('/') + 1);

मेरा परीक्षण आलसी लोड कोणीय की आवश्यकता का उपयोग करने के बारे में निम्नलिखित ब्लॉग पर आधारित है: http://ify.io/lazy-loading-in-angularjs/

आवश्यकता होती है। एक आवश्यकता होती है

आवश्यकताकॉन्फ़िग एक कोणीय app.js भूल जाता है

कोणीय app.js मेरे मार्गों को भूल जाते हैं। js

मैं एक ही कोड एक revel वेब फ्रेमवर्क और asp.net mvc द्वारा परोसा जा रहा था। Revel document.getElementsByTagName ("स्क्रिप्ट") ने बूटस्ट्रैप js फ़ाइल की आवश्यकता के लिए एक पथ का निर्माण किया और मेरे मार्गों की नहीं। js। ASP.NET MVC में यह विज़ुअल स्टूडियो के इंजेक्ट किए गए ब्राउज़र लिंक स्क्रिप्ट तत्व के लिए एक पथ का उत्पादन करता है जिसे डिबगिंग सत्र के दौरान वहां रखा जाता है।

यह मेरा काम करने का मार्ग है। जेएस कोड:

define([], function()
{
    var scripts = document.getElementsByTagName("script");
    var currentScriptPath = scripts[scripts.length-1].src;
    console.log("currentScriptPath:"+currentScriptPath);
    var baseUrl = currentScriptPath.substring(0, currentScriptPath.lastIndexOf('/') + 1);
    console.log("baseUrl:"+baseUrl);
    var bu2 = document.querySelector("script[src$='routes.js']");
    currentScriptPath = bu2.src;
    console.log("bu2:"+bu2);
    console.log("src:"+bu2.src);
    baseUrl = currentScriptPath.substring(0, currentScriptPath.lastIndexOf('/') + 1);
    console.log("baseUrl:"+baseUrl);
    return {
        defaultRoutePath: '/',
            routes: {
            '/': {
                templateUrl: baseUrl + 'views/home.html',
                dependencies: [
                    'controllers/HomeViewController',
                    'directives/app-style'
                ]
            },
            '/about/:person': {
                templateUrl: baseUrl + 'views/about.html',
                dependencies: [
                    'controllers/AboutViewController',
                    'directives/app-color'
                ]
            },
            '/contact': {
                templateUrl: baseUrl + 'views/contact.html',
                dependencies: [
                    'controllers/ContactViewController',
                    'directives/app-color',
                    'directives/app-style'
                ]
            }
        }
    };
});

Revel से चलने पर यह मेरा कंसोल आउटपुट है।

currentScriptPath:http://localhost:9000/public/ngApps/1/requireBootstrap.js routes.js:8
baseUrl:http://localhost:9000/public/ngApps/1/ routes.js:10
bu2:[object HTMLScriptElement] routes.js:13
src:http://localhost:9000/public/ngApps/1/routes.js routes.js:14
baseUrl:http://localhost:9000/public/ngApps/1/ 

एक और अच्छी बात जो मैंने की है वह है आवश्यकता का लाभ लेने के लिए और इसमें कुछ कस्टम विन्यास डालना। यानी जोड़ें

customConfig: { baseRouteUrl: '/AngularLazyBaseLine/Home/Content' } 

फिर आप इसे मार्गों के अंदर से निम्न कोड का उपयोग करके प्राप्त कर सकते हैं। js

var requireConfig = requirejs.s.contexts._.config;
console.log('requireConfig.customConfig.baseRouteUrl:' + requireConfig.customConfig.baseRouteUrl); 

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


2

कुछ इसे थोड़ा "हैकी" का सुझाव दे सकते हैं, लेकिन मुझे लगता है कि जब तक ऐसा करने का केवल 1 तरीका नहीं है, तब तक कुछ भी हैक होने वाला है।
मैंने ऐसा करने के साथ बहुत सारी किस्मत पाई है:

angular.module('ui.bootstrap', [])
  .provider('$appUrl', function(){
    this.route = function(url){
       var stack = new Error('dummy').stack.match(new RegExp(/(http(s)*\:\/\/)[^\:]+/igm));
       var app_path = stack[1];
       app_path = app_path.slice(0, app_path.lastIndexOf('App/') + 'App/'.length);
         return app_path + url;
    }
    this.$get = function(){
        return this.route;
    } 
  });

तब एप्लिकेशन में मॉड्यूल को शामिल करने के बाद किसी एप्लिकेशन में कोड का उपयोग करते समय।
एप्लिकेशन कॉन्फिग फ़ंक्शन में:

.config(['$routeProvider', '$appUrlProvider', function ($routeProvider, $appUrlProvider) {

    $routeProvider
        .when('/path:folder_path*', {
            controller: 'BrowseFolderCntrl',
            templateUrl: $appUrlProvider.route('views/browse-folder.html')
        });
}]);

और एक ऐप कंट्रोलर में (यदि आवश्यक हो):

var MyCntrl = function ($scope, $appUrl) {
    $scope.templateUrl = $appUrl('views/my-angular-view.html');
};

यह एक नई जावास्क्रिप्ट त्रुटि बनाता है और स्टैक ट्रेस को बाहर निकालता है। इसके बाद सभी यूआरएल (कॉलिंग लाइन / चार नंबर को छोड़कर) को पार्स किया जाता है।
फिर आप सरणी में पहले को बाहर निकाल सकते हैं जो वर्तमान फ़ाइल होगी जहां कोड चल रहा है।

यह तब भी मददगार होता है जब आप कोड को केंद्रीकृत करना चाहते हैं और फिर [1]कॉलिंग स्थान प्राप्त करने के लिए दूसरी ( ) सरणी में खींचते हैं।


यह वास्तव में उपयोग करने के लिए धीमा, हैक, और काफी कष्टप्रद होने वाला है, लेकिन नवाचार के लिए +1!
नाथन मैकइन्स

जैसा कि मैंने कहा, वास्तव में ऐसा करने का कोई तरीका नहीं है, इसलिए किसी भी विधि के लिए यह नियम और विपक्ष है। मुझे वास्तव में कोई भी प्रदर्शन समस्या नहीं मिली क्योंकि यह एप्लिकेशन लोड के अनुसार केवल एक बार उपयोग किया जाता है ताकि यह पता चल सके कि ऐप कहां रहता है। इसके अलावा, यह वास्तव में उपयोग करने के लिए काफी आसान है, मैंने अभी पूर्ण कोड नहीं दिखाया है जो इसे कोणीयज प्रदाता में लपेटता है ... मेरे उत्तर को अपडेट कर सकता है।
दान रिचारडसन

0

जैसा कि कई उपयोगकर्ताओं ने बताया है, स्थिर फ़ाइलों का निर्माण करते समय प्रासंगिक पथ सहायक नहीं होते हैं, और मैं ऐसा करने की अत्यधिक अनुशंसा करता हूं।

एंगुलर में एक निफ्टी फीचर है, जिसे $ टेम्पलेटचैच कहा जाता है , जो कम या ज्यादा कैश टेम्प्लेट फाइल करता है, और अगली बार कोणीय के लिए एक वास्तविक अनुरोध करने के बजाय यह कैश्ड संस्करण प्रदान करता है। यह इसका उपयोग करने का एक विशिष्ट तरीका है:

module = angular.module('myModule');
module.run(['$templateCache', function($templateCache) {
$templateCache.put('as/specified/in/templateurl/file.html',
    '<div>blabla</div>');
}]);
})();

तो इस तरह से आप दोनों रिश्तेदार url की समस्या से निपटते हैं और आप प्रदर्शन में आगे बढ़ते हैं।

बेशक हम अलग टेम्पलेट HTML फ़ाइलों (प्रतिक्रिया के विपरीत) होने के विचार से प्यार करते हैं, इसलिए अपने आप से ऊपर कोई अच्छा नहीं है। यहां बिल्ड सिस्टम आता है, जो सभी टेम्पलेट HTML फ़ाइलों को पढ़ सकता है और उपरोक्त जैसे js का निर्माण कर सकता है।

ग्रन्ट, गल्प, वेबपैक के लिए कई html2js मॉड्यूल हैं, और यह उनके पीछे मुख्य विचार है। मैं व्यक्तिगत रूप से गल्प का उपयोग करता हूं, इसलिए मैं विशेष रूप से फैंसी गल्प-एनजी-html2js करता हूं क्योंकि यह बिल्कुल आसानी से ऐसा करता है।

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